News for hackers. Stuff that matters.
Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by cschmatzler on Monday August 14, 2023 @01:38AM (#37117827)
> or inconsistent naming (is_map vs empty?).

fyi, this isn’t inconsistent. https://hexdocs.pm/elixir/1.15/naming-conventions.html

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Munksgaard on Monday August 14, 2023 @02:10AM (#37118014)
While true, I think the larger problem is that it is not intuitive (at least to me) when I can expect a function to be of the `is_` vs `?` form. It's a leaky abstraction.
Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by bitwalker on Monday August 14, 2023 @02:40AM (#37118163)
The only time `is_` is used, is with functions permitted in guards. These are functions defined in Erlang, and only a small handful exist, and you learn them very early on. With the advent of `defguard`, it is conventional to use `is_` with custom guards as well, but that’s the intuition - guards vs general predicates.
Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by Munksgaard on Monday August 14, 2023 @03:04AM (#37118277)
Sure thing. My point is that, if I want to check whether an argument is a keyword list, I have to do extra mental work to guess whether the correct function to use is `is_keyword` or `keyword?`. There also doesn't seem to be a consistent rule I can apply to figure out whether it's one or the other. Conversely, I also get tripped up every time I want to add a guard to a function like, "is the thing I want to test written as a macro or not?".

I understand the reasoning for the distinction and its roots in Erlang, it's just not very elegant to work with.

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by bobwaycott on Monday August 14, 2023 @03:51AM (#37118511)
If you’re having to do extra mental work to guess, it means you don’t have enough familiarity with the language, its type checks/guards, and the standard library. That’s not the language’s fault.

If you want to check the type of a thing, you always want the matching `is_<type>`. It can be used anywhere in your code, including guards. There’s no guesswork involved here. That is the consistent rule.

When you see a function with a `?`, look at the typespec and the function name—give it the argument(s) it expects and it will answer the question on the tin with a boolean. Again, there’s no guesswork. These functions can be used anywhere except guards—that is the consistent rule for boolean functions.

> Is the thing I want to test written as a macro or not?

I have never had to ask myself this question, and I struggle to parse it. Is the “thing” you want to test referring to the value or to the test you wish to perform on that value? Since you’re asking about macros, I’m assuming you mean the guard test. For that, just learn what guards are available[0] (you can also write your own :D ).

[0]: https://hexdocs.pm/elixir/1.15.4/Kernel.html#guards

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by out_of_protocol on Monday August 14, 2023 @04:11AM (#37118617)
> If you’re having to do extra mental work to guess, .... That’s not the language’s fault.

Depends. In this case there are definite rule in place which you can learn. Overall, that's definitely language's fault. On other note, Elixir actually very good at consistent naming

- standard library is designed, not meshed up and grew layer by layer like js/php abomination (erlang one is not consistent and it leaks sometimes)

- Pipe operator by its mere presence enforces correct order of arguments, even in 3rd party code

Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by bobwaycott on Monday August 14, 2023 @04:16AM (#37118640)
It is not a tool’s fault that, upon providing the relevant material that describes its usage and helps a user learn how to use it, the user ignores that and then blames the tool for not working how they want it to work.
Re:Thoughts on Elixir, Phoenix and LiveView after 18 months ... by out_of_protocol on Monday August 14, 2023 @05:03AM (#37118919)
*Assuming naming rules are consistent. After spending 5 years on php, i've never learned its function names and order of arguments. Even daily stuff like `strpos` requires looking at documentation, dozens time per day
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.