Changelog for Elixir v1.11
github.com
github.com
Before, runtime configuration was only available in “releases”, which is Elixir’s packaged tarball for deployments. All other configuration was compile time only. However, running your app locally in a development environment through `mix` would technically compile the app, so even though you didn’t have runtime config, it “felt” like runtime.
Because of this special feature of releases which had their own (and the only) runtime config, you often had to duplicate your config in the runtime config file and the regular compile time config file (for outside releases).
Now, with this new addition, there’s one unified place where ALL runtime config is defined, and which supports runtime config in ALL the different ways you run your app.
To me, this is a huge UX improvement for Elixir devs!
That's awesome, I have a module that is a helper to inject data in a socket to use with liveview but the data that I need isn't present in the dev environment and mocking it is annoying because if I use Mix.env the code in the release breaks, being able to pass an ENV var and just check it to decide to mock it or not will simplify a good amount of code.
I've loved playing with Erlang and Elixir. The concurrency model and approach to failure are fascinating and clearly powerful for certain problems. Elixir's Pheonix feels as productive as Rails. I've read most of Joe Armstrong's books and watched most of his talks.
However, I feel like I can throw my daily driver programming languages including Go, Ruby, Rust... even Haskell at any problem and give or take performance, come out the other end with high quality software at scale.
When I last wrote Elixir, it felt great when I was doing basic Rails shaped work or lower level concurrency heavy networking (I was playing with TUN/TAP interfaces), but I really can't imagine it as a general purpose programming language.
For example I can't imagine scripting in Elixir, but I can and do in the other languages mentioned above. Also I remember trying to write a parser library and it felt way more verbose and unmaintainable than the equivalent Haskell or Rust.
This is hand wavy, but does anyone feel what I'm getting at? Any thoughts?
It's true that most problems are largely manageable by most/all languages.
What I've come to appreciate is how often Elixir has made me a better programmer with its conventions.
Their choices have steered me away from a lot of foot guns and forced me to learn better ways to do things.
I find that Elixir code for these tasks tends to be a bit longer than standard scripting languages, a bit shorter than Go/Java, with performance around Go and slightly better than Java. One of the interesting things I find though is that with the Flow library, bringing it from single to multiple threads tends to require fewer changes - generally I just have to change some uses of Stream to Flow and I'm up and running with a solution that's using all my cores.
"Comparison to Flow You may also be interested in Flow by Dashbit. Both Broadway and Flow are built on top of GenStage. Flow is a more general abstraction than Broadway that focuses on data as a whole, providing features like aggregation, joins, windows, etc. Broadway focuses on events and on operational features, such as metrics, automatic acknowledgements, failure handling, and so on." - (https://github.com/dashbitco/broadway#comparison-to-flow)
Part of what makes Python nice is it's available everywhere. If you have a zero dependency CLI tool, using Python is nice because you can just run the script straight up. The standard library also has good support for argument parsing. I've written a bunch of little tools to help my daily workflow on the command line. I always reach for Python or Bash depending on what I'm doing. I haven't really seen a compelling reason to switch.
Not really. He asked a question about using Elixir as a general purpose programming language so I gave my honest advice and opinion on using it as a scripting language based on prior experience.
Instead of cherry picking my replies out of context, why not go through my entire comment history in all Elixir and Phoenix HN threads? I'll guarantee you'll find tons of positive comments.
Here's a couple to get you started after spending 60 seconds searching:
- https://news.ycombinator.com/item?id=20267184
- https://news.ycombinator.com/item?id=20357572
- https://news.ycombinator.com/item?id=17616692
- https://news.ycombinator.com/item?id=18838449
The first two have over 100 up votes combined for reference.
I'm not looking to argue on the internet, but I do find it strange that so many folks in the Elixir community cannot take any constructive criticism of the language in any way. You realize we're all on the same team right? To build kick ass applications that we enjoy building while users enjoy using it.
For example, the other day someone asked if Phoenix could ever support similar features of Rails such as having something similar to Rails Application Templates. I thought it was a great idea and it was something I wanted too, so I gave as much feedback as I could around why it might be useful to have.
In the end, it looks like most people don't want such generators, or having an ability to build a community around templates like Rails, Laravel and Python. That's based on only a few people commenting to say it's not a good idea and pretty no one else replying saying they wanted it.
You might see that as complaining but I see that as trying to fight for a really useful feature that will help grow the community and make it easier for folks to build applications in the end.
If I didn't care I would have left the Elixir community long ago. I have way better things to do than troll forums. The project I was gung-ho about developing in Phoenix is no longer using Phoenix because after all of those forum posts and struggling endlessly with Elixir I came to the conclusion it isn't the right technology for me to build web apps in. I continue to sometimes post because I hope one day things will change and I'll try to pick it back up again when the community and eco-system is more mature (from a library selection POV, not personal maturity).
For example, you said elsewhere a solution was complicated because it used io lists and a binary constructor but both concepts are explained in Elixir’s official getting started guide. So sometimes it feels you are saying things are complex while you don’t seem to be actively learning the language and some will definitely find that frustrating.
It would be the same if I went to Rust forums, a language I haven’t yet studied in any depth but read a lot about, and constantly said the ownership mechanism is complicated.
Apologies if this comes up as rude. You do seem to be a person open to feedback, so I thought I would drop my $.02.
It's not so much an unwillingness to learn.
It's not being able to write what I think is intuitive code and let's be real now. Programming is all about using tools that make you happy and productive. That's why there's so many different viable choices.
For me, personally (opinion of course), I don't want to have to worry about using binary constructors or io lists instead of strings every time I want to work with a string. I just want to use strings. Fortunately other languages can work with strings efficiently so I don't need to concern myself about such optimizations. I can just focus on the business problem at hand.
When stuff like this happens all the time, yeah, it gets frustrating and eventually you decide a tool isn't right for you. I think I gave it a fair shake too. I wrote a pretty big app twice in Phoenix, once with and once without Live View. I even delayed shipping my product for over a year waiting for Live View to get more fleshed out. And even then it felt like I was pioneering things because I kept running into severe bugs (which I reported).
The lack of libraries is kind of the straw the breaks the camel's back. I can maybe get beyond some of the language issues if it lets me be super productive but I found myself having to implement so many libraries myself because there's no official libraries available for Stripe, AWS, etc.. It just lead to feeling like I was spending more time writing libraries than developing my own app.
In time I hope the Elixir compiler could be smart enough to make optimizations for you behind the scenes and maybe there will be more libraries in the future too. In time Live View will get more fleshed out and polished as well, which is always welcome.
IO lists have useful properties that are not readily available in Ruby and Python, so they come with benefits, and Phoenix uses them to great extent for fast templates.
Binary constructors aren’t optimizations either but the way to construct binaries and strings in Elixir. They’re as fundamental as pattern matching.
The lack of libraries is something I can identify with but please understand it is frustrating to hear over and over again something is hard in Elixir while refusing to learn the language basic concepts because you would rather do it as in Python or in Ruby.
The change in mindset you're demanding from the devs is impossible to accomplish through comments I think. You'd need to develop personal real world relationships with the devs to be able to have such an impact, or create pathways for people with this mindset into the community.
It's the mindset of DHH or Taylor Ottwell what makes their product oriented frameworks more product oriented. Core devs and core parts of the community having this mindset is necessary as a fruitful foundation for more product oriented feature requests I think.
Yeah I totally 100% agree with this. I think it's very much so why Rails and Laravel won't be going anywhere anytime soon. As it turns out most people who are into web development are trying to build products and services.
But I will say that every time I've talked to Jose or Chris (I don't know them personally, I just mean in chat), they always say the best way to offer suggestions or feedback about the language or framework is to post on the forums. It's just unfortunate the community is so against feature requests or open to talking about things.
It just feels like the forums have the same regulars shooting down ideas from anyone new, or feature request threads get little to no replies.
I don't have that impression, but I also got into Elixir knowing that it's not as product focused and more hands on.
For me it was more important that I don't hate the language and programming paradigm I'm mainly using. For purely business oriented stuff or quick MVPs I can still use no-code tools, which in 2020 is really the way to go if you're solo or a very small team.
>It just feels like the forums have the same regulars shooting down ideas from anyone new, or feature request threads get little to no replies.
Most on the Elixir forums seem to be employees and hardcore programmers, not founders and business people. I think even the main devs are employed, this changes how you think about prototyping features or tiem savings if you're never really in that situation and work fixed hours.
I think that the forums are a great learning resource and people seem nice, I mean you can't say that they aren't pacient with you.
except when it doesn't work
which happens more often than not
Elixir is not probably best suited for CLI tools, given the BEAM has slow startup times, but people wrote scripts in Ruby, so it might be acceptable for someone
Elixir scripts can be distributed as releases which include the compiled modules bytecode and the VM to run them or as escripts, which are binary executable that can be run on any system with Erlang installed
Part of what I suspect might make it feel less general purpose is that unless you spend time really learning the internals then it seems somewhat mysterious and constraining. The immutability for example (which most of the time I love) made it a nightmare when I was trying to process and transform deeply nested JSON. I tried a few times in Elixir and just bailed to Ruby where I could directly mutate stuff 5 levels down with ease and efficiency. The code seemed way more straight forward and readable.
How do people deal with things like deeply nested JSON in Elixir? Is there a way to make use of actors to avoid some of the pain points?
For others there's a blog post that introduces it: https://yapee.svbtle.com/nested-data-structures-with-lens
Have you gotten to play with the `put_in/2` [0] and `update_in/2` [1] macros? They're designed to manipulate deeply nested structures like JSON
iex(2)> my_parsed_json = %{"some" => %{"deeply" => %{"nested" => %{"key" => 1}}}}
%{"some" => %{"deeply" => %{"nested" => %{"key" => 1}}}}
iex(3)> update_in(my_parsed_json["some"]["deeply"]["nested"]["key"], & &1 + 1)
%{"some" => %{"deeply" => %{"nested" => %{"key" => 2}}}}
As a side note, a common misconception is that updating a large data structure on the BEAM is inefficient because values are immutable, so you have to copy the whole structure to make a tiny change. This is untrue, as Elixir (and Erlang) "maps" are implemented as HAMTs[2], which support very memory efficient updates by "sharing" the unchanged parts between the the old and updated maps.[0] https://hexdocs.pm/elixir/master/Kernel.html#put_in/2
[1] https://hexdocs.pm/elixir/master/Kernel.html#update_in/2
You're probably right. With a very high-level language like Ruby and an extremely efficient systems language like Rust, you've pretty much got the entire spectrum covered. With libraries like Helix, you've even got an escape hatch if you start with Rails and hit unexpected bottlenecks.
IMO Elixir is nearly ideal for web startups due to productivity, enough performance, easy scaling and a very gentle learning curve. If you've already got all those other tools under your belt, then those pluses are probably less of a draw.
The deployment story for elixir scripts sucks because it is less portable than say ruby or python (the person running the script needs to have elixir and you can't really use library deps in a sane way), but I don't mind it, because it's totally worth having less hassle for the cases where you want a well-defined deployment.
At work, I am using elixir to: orchestrate VMs (this is more traditional elixir-ish), but definitely not really a website or embedded, as a PXE boot provisioning system for metal systems, as a substitute for ansible for laying out software on systems, which are more script-ish, but on the side of "scripts for which you are really going to want to have a consistent deployment story".
At work we use Elixir for web and data ingestion, and I could have used Ruby for web but Ruby is considerably behind for data stuff.
Elixir is fine for one-off scripts, Ruby and Python may be a bit more convenient, but overall they are all too heavy to distribute compared to languages like Go and Rust.
Elixir is also used for high-end embedded and there is the whole distributed programming bits, which is quite specific to its platform, and more complicated to setup in almost all other places.
So overall it does provide some nice coverage across a couple areas although it lacks on other ones (GUIs, ML, etc).
Most semi-popular RubyGems are in v1.0+, have contributions and bug fixes within the past few months, and have a feeling of community around them. There’s even huge companies like GitHub, Shopify, and Basecamp behind some libs.
Elixir mix packages felt abandoned. Most were in the low digits 0.0.x, no commits for over 6 months, and the docs seemed to have a lot of notes in them that it’s early, not maintained, don’t use in production, etc.
Has this changed recently? Can anybody speak to why the Elixir ecosystem feels more empty?
That being said, my company has been using Elixir/Phoenix for three years and while many times there isn't a library for Elixir, often times there is already a stable Erlang library we can use.
https://github.com/h4cc/awesome-elixir is a great source.
We have also changed our habit from looking for third-party libraries to either building our own module which we discovered they are fairly easier to build than we thought, or coming up with alternate solutions that built on top of the powerful Elixir/Erlang technology (e.g. OTP).
Though it may not reach Ruby levels of popularity, it's still just fine. Learning curve is favorable, performance is stellar, and the toolkit that comes with the language is quite featureful. I see other languages borrowing elements from Elixir - especially LiveView and Pattern Matching.
The only hiccups I faced where when I had to roll out my own solutions for a few things (a background job processor, error manager, a mocking module for unit tests, etc.) Even with all this, I'd still say Elixir is worth it, given the performance gain and the patterns it enforces. It all just makes the code easy and understandable.
That said, HN readers from outside the Elixir should know there are great libraries for all of those use cases. Point in case is background job processors—we have plenty of options, though I’m especially fond of Oban[0] (full disclosure, I’m the author).
I completely agree. It's also a great way to avoid complexity you don't need. There are limits, but especially while learning I like to err on the side of fewer dependencies.
BTW, I just now saw that getoban.pro was a thing. It looks great!
However, I started a toy project in it and immediately ran into trouble due to its dynamic nature. Printing function arguments to see what they are, runtime errors... Is there a way to get around this besides adding spec tags on everything?
If you want full static type checking, there is https://gleam.run/ which is a new language, and there’s also something that seems like a full static type checker for Erlang which is going to be released by Facebook soon (they use it internally). See this: https://elixirforum.com/t/facebook-is-writing-a-new-statical....
I, for one, am hoping that the Facebook solution allows us to implement something in Elixir to interface with it so that we can take advantage of it in Elixir, but that is yet to be seen.
That said, I'll take a look at Gleam. Thank you
Another trick I'll do, is to use (abuse) pattern matching:
def foo(%SomeStruct{} = arg, value) when is_integer(value) ...
That also helps Dialyzer narrow down possibilities too and will blow up on runtime.If you use VSCode, the ElixirLS module will auto-suggest @spec's for your functions.
From talking to the WhatsApp Erlang team a little it seems unlikely unlikely that the Erlang type checker will be usable with Elixir I'm afraid.
things are moving in that space, at least for Erlang
https://codesync.global/uploads/media/activity_slides/0001/0...
The improved Compiler checks are a great step in the right direction. I know elixir language isn't going to change much (if at all?) now, so putting more time into things like safety and developer productivity will be warmly welcomed.
For me, is not just the concurrency primitives that I now take for granted, but also the fact that you can write beautiful maintainable code.
Edge cases can live as two line adjustments in ways I don't know how to do in any other language.
When I'm working on the JavaScript (front end) side of an Elixir project, I repeatedly get into these positions where I'm thinking, "Man, I could express this so succinctly and elegantly in Elixir. There's no way in JavaScript that doesn't feel clunky in contrast."
Funnily enough, I think pattern matching is one of the most exciting things to happen in Ruby for a long time. While it isn't on a par with functional pattern matching it's still going to be incredibly useful.
1: phoenix is fast and almost as expressive as ruby (15 ms response times)
2: weird timing bugs don't show up in my code.
3: the tooling is fantastic, a close second second only to rails
4: Ecto beats active record and is easily the best data mapping layer I've worked with. All the nodejs orms I've used in the past felt like clunky toys by comparison.
5: websockets via channels is second to none. seriously, django channels and rails action cable directly copied it but they are not as performant. you can scale a single machine to handle a few thousand connections out of the box and it supports multicluster and long polling to boot.
6: absinthe is great for graphql.
7: live view, think turbolinks on steroids. you can send down updates to the client dom over websockets.
Agreed about all the points, but the tooling could be slightly improved, but that's being done a lot now.
Agreed about all points :-)
Probably the even bigger quality of life improvement for me will be the improvements in recompliation. Greatly reducing the files to be recompiled when a file is touched should be a nice dev experience improvement when working on projects with large numbers of files.
Timex is great but I'm looking forward to having one less dependency on basically every project. ^_^
I thought Jose had said earlier that Elixir was basically "done" a version or two ago, which I was impressed by; how often is software ever finished? But it looks like we're still getting some juicy functionality nuggets.
As an aside, I’ve been playing with Factor recently and it’s been quite the learning experience with concatenative paradigms. I mention it because I was surprised it had erlang-like concurrency models in it (actor, and more).
Fun!
Here is a nice intro to Phoenix Docker releases:
You can easily treat a Phoenix app like you would a rails app, or you can go full on into releases and ship it like a binary. It's all up to you and whether you value easy production debuggability or simplicity, etc.
I've been doing both a lot of TypeScript (for work) and Elixir (for personal projects) for the last few years and I do get a stronger sense of safety from TypeScript (especially during refactoring) but Elixir feels much more concise and fun to work in and the Phoenix event ticketing app I've been running for the last 3 years has been rock solid.
btw I've been programming for 30+ years with all sorts of untyped, dynamically typed and statically typed languages. I still haven't found "the one true language". Something like strongly typed CoffeeScript that runs on BEAM would be close (I've been watching Gleam for a while and I plan to play with it after it matures a bit more).
(I don't find dialyser that strong in terms of performance and code editor help.)
I think Typescript would serve as good inspiration because (1) it's a type system for a dynamic language underneath (javascript) and (2) it uses structural typing which fits well with pattern matching.
Somewhere between 20-30% of the way there. In practice (especially with vscode/elixir-ls plugin) in my experience it does fulfill the 80/20 rule, it catches enough errors that the runtime recovers from the remaining ones (type errors do not cause the vm to panic; just your running "green thread will die and get restarted") with no real customer facing issues.
If you need static types because your team has scaled then it's likely inadequate, but I don't have experience with that.
For my job I was primarily using Elm and Go then for my new job it's been all Elixir. I thought I would miss Elm's compiler (Go, I do not miss).
It's hard to explain, but I find that instead of thinking about what well-defined thing I'm reasoning about, it's about the flow of the data and what shape it happens to be in.
In saying that, with structs and Ecto schemas, we pass those around primarily and pattern match on them too.