3,464 karma · joined March 4, 2010
Software perfectionist.
Open to collaborating and technical co-founding if the idea is right.
Personal web: https://bobwaycott.com
Email: hn@ my personal web domain.
Maybe even just short gifs/videos that show features in action alongside where you currently have some images?
Would love to see it in action—either some video or a way to try it on a private repo. Even if I can’t actually submit a PR review. :)
That is a great skill to have. It’s the kind of skill that saves entire teams of product, design, and engineering folks tons of time. It’s the kind of skill that helps communicate ideas, requirements, and expectations no matter what the problem space in ways that ensure everyone is aligned, understanding, and working together. The absence of this skill usually leads to confusion, wasted effort, frustration, dissatisfaction, and other negative outcomes.
Learning skills often has a compounding effect, as well. Even if a given skill isn’t forever usable in its original form, what you learn along the way continues to pay dividends.
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.
> 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.”
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...
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 ).
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.
You are correct. A keyword list is `[{atom, any}]`.
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.
All your auth logic (and any other bits you need to set while starting up request state) should be a function in a module somewhere that returns expected values. Then, you just care to set these values to Conn and Socket assigns appropriately, keeping in mind that Conns and Sockets aren’t the same—when you have one, you don’t have the other. Thus, on_mount to the rescue:
1. Use Plug pipeline(s) to call your module function to compute and add bits to Conn.assigns (and you can add those values to the session to avoid computing again, if you’d like).
2. Use on_mount to assign_new:
2a. assign_new pulls from Conn.assigns by key for the dead render while you have a Conn.
2b. The fallback function gets that value again when you no longer have a Conn (recompute or pull from session if already there).
Your actual logic should only exist in one place. And there are easy strategies you can use to avoid expensive computations if necessary.
[Edit]: Not suggesting you don’t understand it, just to be clear. I’ve just experienced a lot of coworkers fighting against, abusing, and misunderstanding Conns, Sockets, and assigns.
Typically, I switch via Raycast (or a similar tool like Spotlight, Alfred, etc): ctrl+space, then I type the first letter or two of the app I want, then hit enter. Same thing for starting all apps.
If I know the app I’m switching to was the last active app, I’ll occasionally use cmd+tab. Once cmd+tab is visible, I’ll sometimes use my arrow keys to move between apps.
If I’m switching between active windows of the same app, cmd+`. This is handy for switching between browser windows that have sets of tabs based on what I’m working on, docs I’m referencing, things I’m reading, etc.
My terminal is bound to option+space, so it’s easy to switch to (and I start it with Raycast as explained above).
I also rely on Raycast for positioning all my windows to different sizes and quadrants of the screen with my keyboard. I used to use different apps for all these use cases, but Raycast handles them all and more—calculations, looking up words in the dictionary, etc.
I was lucky enough to build a bunch of the software used consumer-side to enable signing up for and managing fiber internet/tv/phone service, was brought in to establish and run their first internal software team, and built even more cool software to make tech support real-time, improve the lives of CSRs, and more. And they’re now getting into quantum computing. Truly a great group of people trying to take care of their city, and every time I run into anyone, I’m still impressed by what they’re doing.