10 ms·
> So long as the documentation is good, I don't really care how the library itself is implemented. I don't have experience in Elixir, but in my general experi
by jrochkind1 3y ago
> So long as the documentation is good, I don't really care how the library itself is implemented.
I don't have experience in Elixir, but in my general experience what you say is fine until you need to debug something going wrong (or something you don't understand and _think_ is going wrong) in a library, which always happens eventually, no? Or until you want to PR a feature, etc.
- throwawaymaths 3y agoYour intuition as a nom-elixir user is absolutely correct. However it's worth saying that as a working dev, there's almost never a problem in the core++ libraries. Edit: lol looking at the log in elixir slack, and one of the most recent posts is exactly trying to debug something too magical in one of the aformentioned non-core++ libries!!
- sodapopcan 3y agoThose are fair points. In terms of PRing, though, I do think that people are a little too "afraid" of macros. It sometimes feels like people won't learn them out of of principle which is a shame as they aren't that complicated. Though anyone trying to navigate nested macros definitely has my sympathy. No matter how slice it, however, macros are a massive part of what makes Elixir Elixir. A large portion of the language's "keywords" are just macros and they reduce a lot of the boilerplate Erlang forces you to write.
- throwawaymaths 3y agoEEx does macros well. Note that EEx.function_from_x makes you declare the name of the function it instantiates, so it's searchable. GenServer is kind of a "bad example" of a macro. It creates a totally hidden function. Though I guess to be fair 99.9% of the time you really shouldn't be writing genservers in elixir.
- AlchemistCamp 3y ago> 99.9% of the time you really shouldn't be writing genservers in elixir Woah! Why is that? I've written at least one GenServer in nearly all the Elixir projects I've worked on. They seem like one of the base building-blocks to me. Also, if you squint a bit, you'll see that many libraries you're working with are essentially exposing a GenServer interface, with a few extra features.
- sodapopcan 3y ago> Also, if you squint a bit, you'll see that many libraries you're working with are essentially exposing a GenServer interface, with a few extra features. Like LiveViews :)
- pests 3y agoThe only thing I can think of is when developers overuse genserver not realizing it's involving another process and then serializing your requests (behind a queue even) into its mailbox. That may be desirable for some but in-process handling can sometimes be the better choice.
- throwawaymaths 3y agoI've never written a genserver in any professional project I've worked on.... Well, except maybe for a trivial 5 line wrapper enables a global ets. > Also, if you squint a bit, you'll see that many libraries you're working with are essentially exposing a GenServer interface, with a few extra features. I never said you shouldn't be using GenServers. I said you shouldn't write GenServers.
- sodapopcan 3y agoThere's no reason not to write GenServers if you need them. Just don't use them as a class replacement :) But if you need to model some simple runtime state or concurrency, that's what they're there for.
- throwawaymaths 3y agouse Tasks for simple concurrency, Jose has built an awesome module for us.
- dqv 3y ago>It creates a totally hidden function. Are you talking about child_spec/1? `use GenServer` honestly provides some pretty good QoL enhancements over `@behaviour GenServer`. I don't know when or if there was a change to recommending `use GenServer`, but I was pleasantly surprised when I started using it. Especially because I'm not writing new GenServers all the time, having guard rails is nice to avoid being slowed down by remembering all the boilerplate: init/1, handle_x/y, child_spec/1 It's even nice enough to give additional information about why its crashing so you don't get confused why e.g. the handle_call function is working. I make this mistake almost every time I write a new GenServer: def handle_call(:ping, state) do {:reply, :pong, state} end Before, you would just get this meaningless gen_server stacktrace that basically just says "it crashed lol". Now you get the additional hint of "hey you didn't define handle_call/3" when it crashes.
- throwawaymaths 3y agoLast I checked you need to do init/1 by hand. Honestly being more transparent about creating child_spec like `GenServer.create_default_child_spec` would be great. The rest of use GenServer is pretty good, IMO (this is why I wrote 'kind of a bad' macro). I normally hate default implementation of functions but defaulting with an error saying "you forgot this" is reasonable. Edit: just checked, it warns if you don't... I have compiler warnings as error on all my personal projects so that's why I thought you had to do it manually