5 ms·
There's no need to be rude. My point is that it is not obvious, given some arbitrary value and some property to test for, whether that property can be expressed
by Munksgaard 3y ago
There's no need to be rude. My point is that it is not obvious, given some arbitrary value and some property to test for, whether that property can be expressed using a guard or not.
- bobwaycott 3y agoI was not being rude. What you say is not obvious is, to me, a result of not reading the docs, guides, and source code of the language and its standard library. I have seen this pattern repeatedly—those engineers who have learned the language find these things obvious. It’s not an insult, but a push to fill in those gaps. Elixir and Phoenix both have some of the best documentation you will find.
- Munksgaard 3y agoThen explain to me, purely by referencing the Elixir documentation, why URI.char_reserved?/1 is not instead called URI.is_char_reserved/1 such that I can use it in a guard. There's nothing intuitive about memorizing dozens of built-in functions that are (for opaque reasons) different from all the other built-in functions.
- bobwaycott 3y ago> Then explain to me, … why URI.char_reserved?/1 is not instead called URI.is_char_reserved/1 such that I can use it in a guard. Because it is not meant to be a guard—it cannot further empower a function head and pattern match and be optimized and/or inlined by the compiler. Simple as that. Not all expressions are allowed in guard clauses, but only a handful of them. This is a deliberate choice. This way, Elixir (and Erlang) can make sure that nothing bad happens while executing guards and no mutations happen anywhere. It also allows the compiler to optimize the code related to guards efficiently.[0] > There's nothing intuitive about memorizing dozens of built-in functions that are (for opaque reasons) different from all the other built-in functions. I’m sorry, but I’m now struggling to believe you’re discussing this in good faith. Opaque reasons? I see none. It sounds like you either do not like or understand the reasons. It also sounds like you have an expectation that the existence of a boolean function means you can use it in a guard. But that’s your expectations not matching the language’s features and reasoning, neither of which are opaque. There’s nothing intuitive about memorizing dozens of functions? Assuming you’re a software engineer, that is your job. I probably have hundreds of functions memorized, across dozens of standard library modules, in multiple languages. Even if I don’t recall what specific options or arity a function has, I still have enough of it learned because that is my job. It’s what we get paid well to do. [0]: https://hexdocs.pm/elixir/main/patterns-and-guards.html#guards https://hexdocs.pm/elixir/main/patterns-and-guards.html#guar...
- Munksgaard 3y ago> Because it is not meant to be a guard—it cannot further empower a function head and pattern match and be optimized and/or inlined by the compiler. Simple as that. First of all, that's not an explanation, that is handwaving. The real explanation is that URI.char_reserved? could be rewritten using defguard, because it only uses `in`[0]. An arbitrary choice (whether conscious or unconscious) was taken, that this particular standard library function is not allowed to be used in guards. But there is no good reason for it. Secondly, are you claiming that it is not useful to be able to use URI.char_reserved?/1 in a guard? That's obviously bullshit. Finally: The real reason why some things can be used in guards and other can't, is that Elixir must be able to guarantee that no side-effects happen while evaluating a guard[1]. This is a good reason (a good follow-up question is, "why must guards be side-effect free?") and something you can use to form a mental model of which functions you can use in guards and which you cannot, but it is not described anywhere in the Elixir documentation. It's not an easy thing to form a mental model around, but it can be done. To be fair, I think this is a shortcoming in Erlang as well. It would be better to be able to look at the type of a function and be able to tell whether I can use it in a guard or not. Or just allow all functions to be used in guards, such as in Haskell. 0: https://gist.github.com/Munksgaard/ccac61310651d3402571506e4b4ef424 https://gist.github.com/Munksgaard/ccac61310651d3402571506e4... 1: https://www.erlang.org/docs/22/reference_manual/expressions#guard-sequences https://www.erlang.org/docs/22/reference_manual/expressions#...
- bobwaycott 3y agoThe goalposts of this conversation seem to keep moving. It sounds like you don’t like some of Elixir’s choices. That’s fair. I wasn’t hand waving, I was simply summarizing guards in general. We’ve both provided the same explanation regarding why some things can or cannot be guards —you’ve linked to Erlang’s discussion of guards; I’ve linked to Elixir’s. So we both understand guards and their limitations. I’m not terribly interested in arguing about what should or shouldn’t be “guard-worthy”. The built-in guards don’t strike me as arbitrary choices, but as intentional choices as part of designing core language features—that’s all in Kernel, on which everything else depends. The URI module, while a great part of the stdlib, is not core language guard material. I can say that in 7 years, I’ve never needed or wanted a built-in guard to check if a character was a reserved URI char—but I can believe some problem spaces might have use for enhanced guards. Why, I’ve written my own for having more readable and shorter guards for things like empty lists, maps, and more. The ability to compose those from core language guards and features is one of the many things that makes Elixir a great language for my use cases.
- sph 3y agoGuards are very small, very fast functions built in the BEAM VM. is_integer is a guard (in pseudocode: cell.type == TYPE_INTEGER). URI.char_reserved? is too high level to be builtin the VM. Same for the hypothetical is_keyword_list mentioned above. How would you know if something is a keyword list? 1. It is a list 2. The first element is a tuple of 2 elements 3. The first element of the first tuple is a keyword 4. Every other element in the list obeys #2 and #3 What if you pass a list with a million elements to a guard like that? The VM would grind to a halt traversing every single element to make sure the whole thing is a Keyword. This is why there is no such guard. So sure, you might have to consult the docs for what's a guard and what is not, but can also be understood intuitively.
- Munksgaard 3y agoYour point is rendered moot by the fact that `in` is allowed in guards. See my other response as well.
- sph 3y agoThat's a fair observation. Perhaps the exception that proves the rule.
- Supermancho 3y agoLet's burn some karma to point out the toxicity found in many individuals from the functional language crowd. > I was not being rude. Translation: the person asking needs to RTFM because they have a problem with something that is obvious or I don't understand and it doesn't matter which. This isn't being rude. > It’d be immensely more helpful and productive if coming into a language meant one would spend the time to read, learn, and understand that language’s conventions and standard library and read the source code for it! Translation: the person asking is wasting time, being unhelpful and unproductive asking questions > I still have enough of it learned because that is my job. It’s what we get paid well to do. Translation: the person asking must not be doing their job because they don't understand things the way I do (I'm a software perfectionist, ofc) I believe The Erlang (and through extension, Elixir) community seems to engender and defend this kind of back-handed approach to "helping". It doesn't just come off as elitist, it is often little more than taunting. Suggesting that someone pours over documentation (and laughably source code) to explain patterns (or a lack thereof) in a highly abstracted language is counter-productive. For the record, I'll just hide your posts from now on as you cannot seem to help yourself bob.
- jitter_ 3y agoI'm not here to pick a side. I'm sure all of us can be more friendly to each other. However, I'm a bit curious about when you say > Suggesting that someone pours over documentation (and laughably source code) to explain patterns (or a lack thereof) in a highly abstracted language is counter-productive. Isn't that what documentation is for? To learn about whatever's being documented. What would you suggest would be the better way to convey this information? For source code, I can see your point. Although in my experience source code has the benefit that you can be certain that it doesn't lie. It does exactly what it says. Sometimes this can be a really nice benefit when trying to figure out what's going on. Regardless of the language or environment you are in.
- Supermancho 3y ago> Isn't that what documentation is for? I would agree, if everything was documented. The issue at-hand is what is not explicitly documented. What constitutes a guard-worthy function? ie A pure javadoc without any notation about what the API does, is not sufficient.
- jacquesm 3y agoI disagree. I've learned a ton of programming languages over the years and the big differentiator between 'welcoming' and 'gatekeeping' communities around those languages is that the welcoming ones go out of their way to make new people welcome and the gatekeeping ones go out of their way to make the barrier to entry as high as they can. Telling people (several times, actually) in this thread that they should go read the documentation first is rude to the point of being on a different level than just gatekeeping. It makes the assumption that (a) the person didn't read the docs (b) that if they read them that they're too stupid to understand them and (c) that the documentation is perfect and explains things in a way that connects to the persons' level of understanding. None of these may be the case and to assume them is really bad. Consider that you are an ambassador for Elixir in this context and that you are driving others away, which does not serve Elixir and ultimately doesn't serve you. It also stands in sharp contrast to how others in this thread have responded, which I think could easily be used as an example for the 'welcoming' element. Now, it is possible that you are for some reason personally irritated at 'newbies asking stupid questions' but consider that once upon a time you too were a newbie and that there are many fields where you are a newbie today and where talking to people and asking questions will serve as an accelerator to gaining knowledge because interaction is a much faster path to clearing things up than staring at the documentation. Whether Elixir and Phoenix have 'some of the best documentation you will find' is besides the point, that only shifts the line at which interaction with others becomes the main driver of further advancement. And that good documentation wasn't written to serve as a hook for a putdown for new learners of the language.