The progressive introduction of automated type checking in Elixir should serve as a reference on how to improve a programming language gracefully without breaking changes.
So many examples of programming languages have huge breaking changes between versions that end up creating a split in the ecosystem that takes years to resolve.
Thankfully José has been very clear about Elixir being done since at least 2018. The language is stable and the language/core foundation is not changing anymore.
Just a data point on the deps compilation, on a small Phoenix app with mostly stock Phoenix deps:
MIX_OS_DEPS_COMPILE_PARTITION_COUNT=1 mix deps.compile 32.30s user 7.23s system 320% cpu 12.336 total
MIX_OS_DEPS_COMPILE_PARTITION_COUNT=5 mix deps.compile 0.37s user 0.49s system 12% cpu 6.970 total
MIX_OS_DEPS_COMPILE_PARTITION_COUNT=10 mix deps.compile 0.38s user 0.50s system 12% cpu 7.236 total
Machine is a Mac M1 Max, `rm -rf _build` in between each run.
You're measuring a cached compile in the subsequent runs. The deps.compile probably did some native compilation in the dep folder directly rather in _build.
Elixir just keeps chugging along steadily releasing great features and improvements. It's an astoundingly well designed language and the creators have a solid approach to its development. It's a shame I don't get to use Elixir day to day.
Elixir is still confusing, not the language, but the ecosystem, tooling, and philosophy. Is it dynamic or static? Is it compiled or not? If it's not, then why do we have Elixir scripts, which have different file extension? If it uses BEAM and you'd inevitably need to know Erlang when you hit the edge cases, then why not just learn Erlang? If it solves concurrency the "right way" due to supervision trees, why not use Python libraries that also implement the actor model, making Python code concurrent the "right way"? I just don't know which niche applications Elixir targets and excels at.
I really came to love gleam over the last few months. I appreciate elixir getting a type system and remember that this was the big NoGo for me when I explored it a while back. I'd like to give it another chance some time, but I'm worried that it's like typescript - looks typed on the outside but for many libs and packages the types are just a dynamic/any. Is my fear justified? Beam is amazing btw
gleam's 1/0 = 0 is crazy just because the author doesn't want there to be any raises anywhere. problem is, in many real world scenarios 0 is used as a sentinel value that doesn't "just" mean 0. iirc reading somewhere (in a non gleam system where 1/0 = 0) there was a system where everyone woke up to having zero shares because a 0 share tx was posted to everyone's trading endpoint, and a zero share tx means "zero the account".
I’m currently using soketi to broadcast events using a pusher sdk on my api services.
My app is a mix of real time and rest endpoints, and there’s no heavy computation and even if there was I could just call do that one off in Go or something.
Would Phoenix make sense for me? I have some cool collaborative features in the works.
The language itself is maybe OK but the overall experience is not.
On a production build, stack traces look like Erlang code, which is the weird syntax that Elixir tried to improve upon.
Then you have macros, which make code unmaintainable at the 10k SLOC mark, and increasingly harder to maintain as projects get larger.
Running "mix xref graph" on most Elixir projects shows a spaghetti mess.
The toolchain has much room for improvement. Editing, debugging, profiling, unit testing, or pretty much any basic routine development task, involves a tool that's decades behind the state of the art. Even Borland tools from the 80s have a better toolchain.
Building a team around Elixir is hard. You have to train people on the job and they will probably not write idiomatic code that takes advantage of the language. Or deal with people that won't stop selling you how great the language is.
And the documentation for most of the projects you will use is full of noise, with few workable examples, grandiose claims of performance and fantastic treasures, and the articles are a great read if you want to waste your entire evening.
Support for massive concurrency is nice but you are realistically not going to need it. If you do need it then yes, Elixir can be a good tool for the job.
That's neat, Elixir is one of the most promising web development environments in my opinion, every time I come across it professionally it is a level above what we normally encounter, as are the teams that are using it. Elixir keeps setting standards for how you should approach this kind of continuous development.
If anyone is interested in helping out on an real-world open source Elixir project - a major component of what used to be Mozilla Hubs and is now an independent project is written in Elixir: https://github.com/Hubs-Foundation/reticulum
Very cool! As a professional Elixir developer who loves types, I'm so happy to see them coming more and more to the language.
I have a question about how the type inference works. Dialyzer, which also attempts to do type inference, uses "success" typing which means it will not flag something if it could work. It tries to minimize false positives. In practice, this means it hardly ever catches anything for me (and even when it does warn about something, it's usually not real anyway!), so I don't find it that useful.
Does this approach use "success" typing as well? I found the `String.Chars` protocol example interesting, since I've had my fair share of crashes from bad string interpolations. But in the example, it's _clearly_ wrong, and will fail every time. That's not that useful to me because any time that code is exercised (e.g. in a simple test) it would be caught. What's more useful is if some particular code path results in trying to interpolate something wrong.
I know under the hood, the Elixir type system has something to do with unions of possible values, so it is tracking all the things that "could" be passed to a function. Will it warn only if all of them fail, or if any of them fail?
This might be hot take, but I really wish Elixir had more variety in its ecosystem -- particularly in its client-side ergonomics.
I absolutely love the language, the way it fits into the Erlang runtime, and especially Jose's stewardship. But Phoenix/LV don't jive with my brain nearly as well as Elixir itself does. Additionally, the push towards native development never evolved to a place where it could realistically supplant Expo & RN for me.
This probably sounds insane to anyone who hates how the TS/JS community has a million different frameworks, but I think the upside of all that chaos is that a plethora of new ideas that get explored, and the truly exceptional ideas end up getting adopted anywhere.
My gut feeling is that the Elixir world has a TON of amazing ideas that have yet to be explored.
20 comments
[ 5.5 ms ] story [ 46.4 ms ] threadSo many examples of programming languages have huge breaking changes between versions that end up creating a split in the ecosystem that takes years to resolve.
Thankfully José has been very clear about Elixir being done since at least 2018. The language is stable and the language/core foundation is not changing anymore.
https://www.youtube.com/watch?v=suOzNeMJXl0
Truly outsanding work and stewardship.
I can only think of 2: python 3 and perl 6.
Those two were very traumatic so it's not surprising it feels like more.
dynamic() > boolean()
integer() > boolean()
I was a fan of Ruby -- because of it's pragmatism and subjective beauty -- but then I got into type systems.
Elixir now also has a type system and, so does Ruby...
Though I know program in Kotlin, which syntax-wise is very much a "typed Ruby".
My app is a mix of real time and rest endpoints, and there’s no heavy computation and even if there was I could just call do that one off in Go or something.
Would Phoenix make sense for me? I have some cool collaborative features in the works.
The language itself is maybe OK but the overall experience is not.
On a production build, stack traces look like Erlang code, which is the weird syntax that Elixir tried to improve upon.
Then you have macros, which make code unmaintainable at the 10k SLOC mark, and increasingly harder to maintain as projects get larger.
Running "mix xref graph" on most Elixir projects shows a spaghetti mess.
The toolchain has much room for improvement. Editing, debugging, profiling, unit testing, or pretty much any basic routine development task, involves a tool that's decades behind the state of the art. Even Borland tools from the 80s have a better toolchain.
Building a team around Elixir is hard. You have to train people on the job and they will probably not write idiomatic code that takes advantage of the language. Or deal with people that won't stop selling you how great the language is.
And the documentation for most of the projects you will use is full of noise, with few workable examples, grandiose claims of performance and fantastic treasures, and the articles are a great read if you want to waste your entire evening.
Support for massive concurrency is nice but you are realistically not going to need it. If you do need it then yes, Elixir can be a good tool for the job.
Having the $lang_ecosystem address this sounds godsent. Unfortunately we don't use Elixir at $work.
I have a question about how the type inference works. Dialyzer, which also attempts to do type inference, uses "success" typing which means it will not flag something if it could work. It tries to minimize false positives. In practice, this means it hardly ever catches anything for me (and even when it does warn about something, it's usually not real anyway!), so I don't find it that useful.
Does this approach use "success" typing as well? I found the `String.Chars` protocol example interesting, since I've had my fair share of crashes from bad string interpolations. But in the example, it's _clearly_ wrong, and will fail every time. That's not that useful to me because any time that code is exercised (e.g. in a simple test) it would be caught. What's more useful is if some particular code path results in trying to interpolate something wrong.
I know under the hood, the Elixir type system has something to do with unions of possible values, so it is tracking all the things that "could" be passed to a function. Will it warn only if all of them fail, or if any of them fail?
I absolutely love the language, the way it fits into the Erlang runtime, and especially Jose's stewardship. But Phoenix/LV don't jive with my brain nearly as well as Elixir itself does. Additionally, the push towards native development never evolved to a place where it could realistically supplant Expo & RN for me.
This probably sounds insane to anyone who hates how the TS/JS community has a million different frameworks, but I think the upside of all that chaos is that a plethora of new ideas that get explored, and the truly exceptional ideas end up getting adopted anywhere.
My gut feeling is that the Elixir world has a TON of amazing ideas that have yet to be explored.