News for hackers. Stuff that matters.
Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by bobwaycott on Monday August 14, 2023 @02:58AM (#37118249)
The larger problem is not reading the docs to understand and learn language conventions. If one reads the docs, it is immediately clear that the `is_` prefix denotes a function that returns a boolean and can be used in guards. The `?` form is for all other functions that return a boolean. Which means one will gain an intuitive sense of every function you see in the `is_` and `?` forms.

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! It pays serious and continuous dividends, and is the fastest way to gain an intuitive sense for the language.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Munksgaard on Monday August 14, 2023 @03:08AM (#37118291)
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.
Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by bobwaycott on Monday August 14, 2023 @03:27AM (#37118377)
I 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.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Munksgaard on Monday August 14, 2023 @03:47AM (#37118490)
Then 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.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by sph on Monday August 14, 2023 @04:31AM (#37118737)
Guards 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.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Munksgaard on Monday August 14, 2023 @04:42AM (#37118802)
Your point is rendered moot by the fact that `in` is allowed in guards. See my other response as well.
Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by sph on Monday August 14, 2023 @05:37AM (#37119110)
That's a fair observation. Perhaps the exception that proves the rule.
Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by bobwaycott on Monday August 14, 2023 @04:09AM (#37118604)
> 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#guar...

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Munksgaard on Monday August 14, 2023 @04:39AM (#37118780)
> 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/ccac61310651d3402571506e4...

1: https://www.erlang.org/docs/22/reference_manual/expressions#...

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by bobwaycott on Monday August 14, 2023 @06:11AM (#37119294)
The 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.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by josevalim on Monday August 14, 2023 @06:34AM (#37119418)
I have read this whole subthread and it is quite interesting because it is clear everyone involved knows what they are talking about, but speaking past each other. :)

I agree with you that you have to build a mental model and you have to memorize (or consult) which guards are available, but arguably the `is_foo` vs `foo?` distinction here is a positive one, because it only takes a glance to know if it is a guard or not (and the majority of guards have the `is_*` prefix).

You are correct URI.char_reserved? could have been a guard - but that should not be a confusion point for a user of the library - it is clear it is not a guard function. The confusion only arises as a contributor once you read the source as to why a certain choice was made (in this particular case, char_reserved? was written before defguard existed, but even if I wrote it today I am not sure I would consider the possibility users would invoke it in guards).

Btw, I know you know this. I just hope this clarifies the whole discussion a bit for others!

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Supermancho on Monday August 14, 2023 @04:41AM (#37118794)
Let'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.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by jitter_ on Monday August 14, 2023 @05:09AM (#37118958)
I'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.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Supermancho on Monday August 14, 2023 @03:28PM (#37125676)
> 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.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by josevalim on Monday August 14, 2023 @07:55PM (#37128369)
> The issue at-hand is what is not explicitly documented. What constitutes a guard-worthy function?

https://hexdocs.pm/elixir/1.15/patterns-and-guards.html#guar...

Plus the docs lists on the sidebar which custom functions are guards. Examples: https://hexdocs.pm/elixir/1.15/Integer.html#guards

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Supermancho on Friday August 18, 2023 @06:42AM (#37173805)
The question was about why not what is allowed as a guard. Perhaps this was not clear amongst the noise.
Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by josevalim on Sunday August 20, 2023 @06:26AM (#37197801)
Second paragraph of the first link:

> 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.

If it can be improved, please let me know.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by bobwaycott on Monday August 14, 2023 @05:39AM (#37119124)
You are reading an incredible amount of hostility into my comments that is not there.

> 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.

That’s an incredibly uncharitable translation and doesn’t accurately match my meaning or intent. At each point in this thread, other commenters and I have provided explanations and linked documentation. Each response has been of the form “sure thing / that’s true, but it’s not obvious to me”. Then a repetition of the core complaint. This has led to more attempts at explanation and linking documentation, just to get the same response. Saying RTFM is one thing, but it’s simply not rude to suggest reading docs would bring clarity (and suggesting reading docs would help is not the same as answering “RTFM”).

> Translation: the person asking is wasting time, being unhelpful and unproductive asking questions

Not at all. I haven’t once felt like the person asking was wasting time, being unhelpful, or being unproductive asking questions. My comment was simply saying that it is immensely more helpful and productive [to a person entering Elixir for the first time] to read Elixir docs and guides and, where accessible, the language/stdlib source (it’s all Elixir), because it pays serious and continuous dividends on the journey of mastering the language—compared to jumping in deep before you’ve built an intuitive understanding of how it works. It wasn’t a slight or an insult.

It was the same advice I received early in my career in a completely different language that has proven itself true with every language I’ve learned since.

> 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)

Amusing weaponization of my HN profile, but your translation is still unfair. Complaining about memorizing a handful of guard functions felt to me like complaining about doing the job. I don’t expect anyone to understand things the way I do. Nor was I trying to backhandedly insult or taunt.

I spend nearly half my working hours each week reviewing thousands of lines of Elixir code from hundreds of engineers, pairing with 10s of them, helping people learn, explaining how things work, and learning new things myself alongside them every day. Every time anyone doesn’t understand something, it’s an opportunity for us to pair up, dig in, review docs, come up with new explanations, show off code to explain and cement concepts, etc. That’s not the same thing as complaining and labeling something as a language problem, have multiple people trying to help explain it, but keep saying “but it’s not obvious and doesn’t match my expectations, so that’s Language X’s fault.”

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Munksgaard on Monday August 14, 2023 @06:19AM (#37119347)
> but it’s simply not rude to suggest reading docs would bring clarity

It's pretty rude to assume/insinuate that I haven't read the documentation just because you misunderstood my initial concern.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by freedomben on Tuesday August 15, 2023 @12:15PM (#37135761)
It's been quite a while since I saw such a mismatch/meltdown on HN like this. Don't take it too personally. I did think your comment (the one about read the docs & some source code) was a little dismissive, but in context of the rest of the thread it makes some sense. It does annoy me greatly when people spread the same thing across 10 different comment branches, ignoring answers they got in other branches, so I very much sympathize with you. In fairness HN obscures the timestamps after an hour, so it can be really hard to figure out the order of comments when reading later. Biggest HN feature request: I would love to be able to see the exact stamp (to the minute at least).

I think you did a fine job, and I also commend you for having thicker skin and not responding to the personal attacks on you in-kind.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by jacquesm on Monday August 14, 2023 @05:46AM (#37119157)
I 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.