What a terrific write up! I highly recommend the read.
I too had an ephiphany when I realized Elixir was actually a Lisp. The language went from mildly interesting to "holy crap I think this could be my favorite language." Add on some wildly productive and pragmatic frameworks like Phoenix, Nerves, and increasingly Nx, and you've got a hell of a toolkit.
My biggest criticism of Elixir has been the difficulty of writing quick scripts, but that story has improved greatly over the last couple of years. I still turn to Ruby for scripts (especially since it's often present on systems and so easy to install), but this is a good reminder that it's time to try Elixir again for that. In some ways it may be better, such as dealing with dependencies. For exmaple I try hard to avoid using any non-standard libs with Ruby scripts so I can just use the system ruby, and don't have to ship a Gemfile and/or install any gems, or mess with chruby/asdf. With Elixir that story looks even better since the deps can be part of the script itself.
> I too had an ephiphany when I realized Elixir was actually a Lisp.
Is it actually? Last time I looked at Elixir (granted, that was a while ago), the syntax for writing macros was different than the syntax for writing ordinary code, so it fails even at a simple thing like that, it doesn't seem to support homogeneous meta-programming at all.
But again, I feel like I might be wrong here and I'm happy to be proven wrong.
Ya, it's not actually a lisp. I can't find the source but José has stated part of the idea was to give you lisp-like metaprogramming with a non-lisp syntax (sorry, José, if I have mis-quoted).
Even the regular syntax is sort of lispish, though, if you remove the syntactic sugar. It's all macros and datastructres.
A bit pedantic I guess, but that still uses some syntactic sugar (optional brackets and keyword syntax). Removing all syntactic sugar would look like this:
You can write macros (as well as functions, actually) that accept AST and emit transformed AST back. It has quote and unquote. Turns out that it doesn't need homoiconicity to accomplish Lisp-level macro capability, which means it has all the power of a Lisp but with actual syntax (which is, like it or not, more appealing to many people) in a language with deep pattern-matching and completely immutable data guarantees.
> For exmaple I try hard to avoid using any non-standard libs with Ruby scripts so I can just use the system ruby, and don't have to ship a Gemfile and/or install any gems
The ruby "story" for Gemfile dependencies for single-file scripts have gotten a BIT better since possibly last time you looked at it.
It will of course necessarily involve installing gems still though. Ideally for your use case, I feel like you'd want to install them to a local (not system-default) location ... which is ordinarily possible with bundler, but oddly the maintainers seem to think it's an anti-use-case for inline bundler? https://github.com/rubygems/bundler/issues/7131. I dunno.
Anyway, I put this here not to convince you, your decision is reasonable, but just other info for other readers.
Problem with writing scripts in Erlang VM is the slow startup time...it isn't suited for that. Although I love it for pretty much everything else besides scripts and executables.
Yeah, this miffs me too (a half second startup time, locally), which has got me even looking at languages like Idris that can compile down to C and then thus to an instant-start app.
Re Elixir for scripting, what's the point? Procedural Ruby, Perl, Python or bash have been around for decades and are exactly what you need for short sysadmin scripts. Elixir/Erlang's niche is massive lightweight conucurrency and is the wrong tool for this domain.
The Enumerable APIs, regex handling, low-bullshit functional approach, and great REPL make it a pretty nice scripting language. I've done quite a few Advent of Code puzzles with it, and it always feels like such a nice multitool for chewing up the input files into workable formats.
It's not the first tool I'd reach for, I'm still a filthy bash hacker at heart, but I could definitely see using it for the right problem.
It's also just fun to write, which is valuable in its own way.
If your point is that the potential use cases overlap too much with Ruby, I mean, fine, write Ruby. I like Elixir more. I'm not picking either language for pure performance, but rather for ergonomic purposes, so we're into kinda subjective territory.
I often write some little toolets in Elixir, just to hone skills and give myself an opportunity to explore the libray. Often after I e first written it in Python. I agree it feels a little misaligned, but it’s nice to be able to use it for other reasons.
It's nice not to have to switch languages. I use multiple languages but we're not infallible; it would be better if we could write it all in one perfect language that we know really well. Just explaining the desire, I've never touched elixir.
$ elixir test.exs
hello, world!
$ hyperfine "elixir test.exs"
Benchmark 1: elixir test.exs
Time (mean ± σ): 471.1 ms ± 2.6 ms [User: 187.4 ms, System: 83.1 ms]
Range (min … max): 467.1 ms … 475.6 ms 10 runs
Compared to:
$ ruby test.rb
hello, world!
$ hyperfine "ruby test.rb"
Benchmark 1: ruby test.rb
Time (mean ± σ): 36.3 ms ± 2.6 ms [User: 26.0 ms, System: 8.4 ms]
Range (min … max): 34.5 ms … 53.6 ms 53 runs
In practice, I've been able to get the ruby startup time to as low as 6ms - this is what I use for scripts running as keyboard macros, for example. I cannot practically use elixir for that.
Huh, interesting. I bet for keyboard macros, it would work better by invoking a call to something that is already running to reduce startup time. Kinda like the emacs server.
BEAM should still be able to compile new code on the fly, for one-off scripts
> keyboard macros [...] would work better by invoking a call to something that is already running to reduce startup time
Maybe, but that comes with two disadvantages:
- I would have to re-architect my scripts to work like that, and run a server with uncertain memory costs perpetually; and
- I would have to use something with faster start time to run the call on my keyboard macros, e.g. bash, which would mean writing bash instead of elixir/ruby and/or being clever.
I too had an ephiphany when I realized Elixir was actually a Lisp. The language went from mildly interesting to "holy crap I think this could be my favorite language." Add on some wildly productive and pragmatic frameworks like Phoenix, Nerves, and increasingly Nx, and you've got a hell of a toolkit.
My biggest criticism of Elixir has been the difficulty of writing quick scripts, but that story has improved greatly over the last couple of years. I still turn to Ruby for scripts (especially since it's often present on systems and so easy to install), but this is a good reminder that it's time to try Elixir again for that. In some ways it may be better, such as dealing with dependencies. For exmaple I try hard to avoid using any non-standard libs with Ruby scripts so I can just use the system ruby, and don't have to ship a Gemfile and/or install any gems, or mess with chruby/asdf. With Elixir that story looks even better since the deps can be part of the script itself.