Elixir has always been a pleasure for me to work with. Maybe true with most FP languages as well.
The main positive I see is that I can easily navigate through code (due to absence of complex objects/classes) and the standard library seems to be very extensive.
The language was also easy to get into. My only complaint is that the IDE support for intelliJ(through the plugin) hasn't been impressive though I can live with it.
For me, the benefit vs OO is that everything is explicit. If I'm calling into a function from another module, it's almost always clear which other module -- if I need to see what it does, I can go look and the code is likely to be there. Compared to something in OO where I've got an object to call a method on, and it may actually be an object that extends/implements making it much harder to find code (IDEs can often help, if you've taken the time to setup the IDE).
You can call into a module with a variable, but it's rarely done, outside of some specific types of code interaction (ex: structural event loop processing like gen_server takes a Module to callback into).
Of course, when sending messages to processes, there's not really anything in code to indicate where those will be processed, and I don't know that IDEs help there either. Usually, code organization helps, but it's not required.
Caveat: my experience is with Erlang, not Elixir, but should generally apply.
Spot on!
I did some work on OTP and it seemed to be neat. I did learn Go just to compare how easy/fun it would be to work with. I liked Go but I came back to Elixir because of pattern matching, minimal configuration and readable semantics.
Not to mention, there's not much boilerplate to deal with and we've got useful control structures like the very readable `cond`s instead of if {} else if { } blocks (Although you can use these, it is generally discouraged in Elixir). I will tell you that being pushed towards writing "cond" s and "when"s, "with"s has guided me towards achieving a better and more readily understood codebase.
The explicitness of Erlang is exactly what Elixir is lacking. A /lot/ is done via macros. This makes it really easy to build domain-specific language extensions, but it also means that you'll have to learn what they are doing to fully understand the code.
In Erlang, the few simplifications you get are very local (as long as you don't apply a parse_transform on your whole project, which is rarely a good idea).
I agree, and I'm a rarity maybe, because I think it is much easier to understand and debug Elixir if you learn Erlang first. You don't have to, in order to code in Elixir, but understanding what was going on under the hood made it much easier for me to work with Elixir.
I understand how that could be a problem. However it never was with the countless DSLs I saw in Ruby. The trick is never write one. Only use the ones of widely popular projects.
I never wrote a macro in Elixir (only for experimenting with them), nobody ever did in the projects I worked on and I'm perfectly happy with that. On the other side everybody uses macros, mainly with/do/else. I wish they implemented it as keywords of the language. They could probably have spared us the annoyance of converting code from = to <- and comma everytime it is moved inside a with and viceversa. That's the part of the syntax that I like less.
I've found most Elixir projects I've taken a look at to be surprisingly easy to follow when I've needed to.
I've dug into Ecto, Ecto SQL, Elixir itself at times. This was just because I was trying to figure out some corner-case behavior. The overhead of understanding someone else's classes when I tried similar things in Python was always just a much heavier mental load. Idiomatic or not.
As mentioned by another comment, the important thing is that each function you need to read can pretty much be read on its own. You might need to follow a few trails. But the way a library can hide where the magical state comes from in a Python class is sometimes maddening. I know, because I've written that code.
I find Elixir incredibly readable, nicely writable and the mental overhead continuously lower.
Not sure if it's me but I find decorators a terrible annoyance most of the time if I am reading random code in the wild. It feels like magic with a can of worms that you have to go through multiple files to fully understand.
I like them for use in some bigger frameworks but overall, they seem to provide negative value to me as a reader, often confusing names doing some magical coating which could very well be solved with pure function composition.
I have noticed some python projects making heavy use of it... they rely on you to read their guide to write code instead of switching and using the project fine because you know the language. Sort of like another DSL?
Elixir hits the balance for me between being not too intense (haskell) and friendly usable with a nice community.
One hurdle that was difficult for me was understanding Behaviors (which are an abstraction used in both Erlang and Elixir). On the one hand, a Behavior is much like an class/object: it has public methods, internal state, polymorphism (via message passing) and to some extent a notion of inheritance. According to Alan Kay, it's more Object-Oriented than Smalltalk!
However, a Behavior runs in it's own process. Like a typical class, public and private functions are defined in the same file This makes reading the code where a Behavior is defined more difficult because the public methods are executing in the client process, but the callbacks (i.e. private functions) are executing in the Behavior's own process.
One insight I gained from working with Erlang was that the "academic" notion of OOP modeling (i.e. model the entities of your domain as discrete objects) works much better with Erlang's proceses/Behaviors than it ever did with classes/objects in languages like Java.
Objects in languages like Java, C#, Ruby, JS, etc. are much at modeling the architectural components of a system, than at actually modeling domain entities directly. That's actually partly why I really the Pony language: it combines both objects as processes (called Actors) and objects as components/capabilities (called Objects).
FYI: behaviour is an API specification for modules, they don't have to run in their own processes.
However, it is the case that the most commonly used behaviours are gen_server, gen_statem, supervisor, etc, which do live in their own processes, and it is arguably most useful to use behaviours to determine the callbacks that an abstracted, general process-managing module uses to hook into the module you write that describes the implementation of a GenServer.
For an example of a non-process-bound use for a behaviour, one could have "ping" behaviour, which describes running an ICMP ping. You could then describe in abstracted form, the common points between an implementation that uses the linux standard ping, fping, a FFI call to low-level OS hooks and network stacks, a call to the new OTP 22 socket module. Or, in a test environment, write a module where it's backed by a stateful lookup table, where you can assume a ping response, but selectively turn off ping responses to IP addresses to simulate a failed ping response and verify downstream effects.
> Behavior is much like an class/object: it has public methods, internal state, polymorphism (via message passing)
> a Behavior runs in it's own process
This doesn't sound right; a behaviour is just a set of functions to be implemented in a 'callback module'; you seem to be talking about processes and modules. I agree with your points though.
> This doesn't sound right; a behaviour is just a set of functions to be implemented in a 'callback module';
Going back, I see that you are right: the Behavior is technically the common pattern that is shared across specific processes. Is there a name for a process that is defined in a callback module?
And really, this complaint about confusing modules spans to more than just callback modules. Most processes define both the client and server functions in the same module. For small modules it's not too big a deal, but even then it is very difficult for someone new to the language to learn how follow the flow of data.
Dave Thomas has some interesting ideas about this and other problems, but as I don't do Erlang programming professionally at the moment I haven't had time to really dig in deep.
> Is there a name for a process that is defined in a callback module?
I don't think there really is. Where I was working, we would just say this process is a gen_server (or whatever), as if it was a type of process, but this is more of an emergent property of the environment, than a named property. If enumerating the processes, you can guess a process is a gen_server based on erlang:process_info(initial_call, Pid), but that's not definitive because it could have started as something else, then used gen_server:enter_loop to become a gen_server, or started as a gen_server and then become something else.
Naming the behavior the same as the module, and including client apis and server and the behavior in the same module is legitimately confusing as well; although, all that being in the same place can be nice, too.
A behaviour defines an interface a module can implement, nothing more. A good example of a behaviour that doesn’t involve any process is the SSL session cache:
If you implement your own cache module (backed by a file, DB, whatever) and it respects this interface, you can then pass it to the SSL functions and they’ll use it instead of the default cache.
It just happens that gen_server is both the name of a behaviour, and the name of a module, which can be a bit confusing. The gen_server module implements a generic server process, which is customized by passing it a module that implements the gen_server behaviour (as an argument of `start_link`).
Yeah, the thing that has driven me to FP, and made Elixir/Erlang such a joy is that data and state are like not coupled (not saying they have to be in OOP, but god damn if I haven't had something that should only do a read do a write and fuck me too many times to count). Given the same input a function will always produce the same output, because values are constant. I've been writing Elixir for like 5-6 years now and four of them professionally, and I hope I never go back to a non FP language (save Rust or mind-boggling pay).
It's kind of mind blowing when you realize, at any point in your program, you can simply serialize out your data, inspect it. Try that with a class, good fucking luck with whatever marshaling system you have...
In Elixir/Erlang, all you (generally speaking) ever have are:
- Strings (binaries, bit-strings, charlists)
- Numbers (integer, float)
- Lists (a list of things)
- Maps (a set of keys and values)
- Structs (a map with a predetermined set of keys)
The biggest thing to keep in mind coming to a BEAM language from somewhere else is that both the language you're using (Elixir/Erlang/LFE[1]/etc) and the runtime were explicitly designed together to solve a specific category problem (distributed systems). This very unique combination provides, IMHO, the best environment you could ever want to run code in...
In most languages you start up your server in its own process. Want to debug it? You gotta restart the process and then put your debug point in. Not the case in Erlang/Elixir, here's how I start up the Phoenix framework:
iex -S mix phx.server
What that does is both (a) starts the server, (b) opens up an interactive repl for the running application. You can then interact with the running system as it is, and holy shit does it make debugging wonderful.
Something in Erlang just too slow, write a NIF (but really don't; this (NIF) is a last resort and the only way to you're likely to ever actually crash the VM). You can see a VERY simple example I have in the `wyhash_ex` directory: https://github.com/tehprofessor/shorts (please note shorts is just a toy project, and not quite complete as I got obsessed with the `gen_tcp` part).
Finally, while yes processes, are the fucking peanut butter, jam, and jelly-- you really don't end up using them directly that often in your day to day life. If they aren't making a ton of sense or you don't find yourself using them everywhere, don't sweat it-- when you need to they'll be the obvious solution (even if implementing that solution isn't obvious at first b'cuz learnings).
If you have any Elixir questions, I'm available on Twitter at the same handle as my Github links. Also, the Elixir slack is quite great as well.
> I've been writing Elixir for like 5-6 years now and four of them professionally, and I hope I never go back to a non FP language (save Rust or mind-boggling pay)
Is there such a big market for Elixir these days? I thought it was very nichey yet.
Yeah, there seems to be, generally speaking it's tilted towards more senior level folks, and projects, as Elixir isn't really on anyone's radar as an entry level language. Plus, understanding the concepts that make OTP great usually requires moderately thorough understanding of asynchronous and parallel programming.
I think it's been growing pretty steadily, IMHO, because Elixir/Erlang is such a wonderful platform for development, BEAM is extremely battle-tested at this point, and performance is quite good for how easy it all is... also, while I spoke against it, when you absolutely must, to you _can_ write something in C fairly easily (I've _never_ had a good time trying to do C-interop in Ruby or JavaScript for example).
Wow, after searching for jobs for Elixir I found that the market is not so small as I have thought (even in for my region!).
I always wanted to learn it deeply, since I appreciate functional and the concept of Actors, but never thought I would find a job for it easily... I'm changing my mind now.
Since you talked about rust in your original post, rustler allows you to write NIFs that can't crash the BEAM, never felt the need to use it, but at least it exists.
I'm totally aware of Rustler :) but it's a nice tool to share! I was mostly trying to speak to the real world environment where you have a simple routine or interface already prepackaged and you want access to it... Not that you can't use Rustler, but just being able to access the C interface directly is comforting (and sometimes easier than adding another compilation step between them even if it is _safer_ (e.g. prototyping)).
Most importantly Elixir and their other open source projects are being transferred over to community control and will not be affected by this acquisition.
For the Elixir programming language in particular, José Valim and the Elixir Core Team will continue developing and maintaining the programming language in the same capacity as they have been doing over the last few years, independently from Plataformatec and Nubank. We are in touch with the Elixir Core Team to transfer all assets, including the existing trademarks and the Elixir website, to their control.
> For the Elixir programming language in particular, José Valim and the Elixir Core Team will continue developing and maintaining the programming language in the same capacity as they have been doing over the last few years, independently from Plataformatec and Nubank. We are in touch with the Elixir Core Team to transfer all assets, including the existing trademarks and the Elixir website, to their control.
The way this reads, it sounds like Nubank isn't going to keep supporting these open source projects by letting their employees spend company time on them... I hope that doesn't starve elixir of resources.
José explicitly addresses that concern. Of the core Elixir team, only José works at Plataformtech. Also it’s stated that the language/syntax part of Elixir is largely "done", which imho is awesome.
Also it’s stated that the language/syntax part of Elixir is largely "done", which imho is awesome.
Yeah and that leaves huge chunks like tooling that aren't done or mature. When I walked away from Elixir and Phoenix it was right around when bitwalker abandoned distillery leaving the deployment story unsupported. Blech.
> Yeah and that leaves huge chunks like tooling that aren't done or mature.
That's why I said the syntax is largely done. They're still actively working on tooling as this release shows. The compiler has some useful improvements. IMHO, a stable syntax leaves more focus on improving the tooling as in this release. It seems to work well for Clojure as well.
> When I walked away from Elixir and Phoenix it was right around when bitwalker abandoned distillery leaving the deployment story unsupported. Blech.
Too bad to hear. Luckily, bitwalker's work has largely been integrated into Elixir in v1.9. So now it will be supported going forward by the core team which makes more sense than one developer supporting a core part of Elixir's tooling.
Recently the Erlang Ecosystem Foundation [EEF](https://erlef.org) was founded and supported by a several companies and the community to ensure the Erlang (including Elixir) ecosystem is maintained.
That's why I said the syntax is largely done. They're still actively working on tooling as this release shows. The compiler has some useful improvements. IMHO, a stable syntax leaves more focus on improving the tooling as in this release. It seems to work well for Clojure as well.
That pretty well sums up why I rather like Clojure and Rust but not Elixir: tooling is an afterthought, at best, with Elixir.
Luckily, bitwalker's work has largely been integrated into Elixir in v1.9.
That's disappointing to hear. Distillery was a cobbled together mess of bash (not even POSIX!) scripts that should've been put out to pasture ages ago. Elixir has three major problems from my POV: developer tooling is an afterthought, portability is an afterthought, and build artifacts / deployments are unwieldy. Distillery embodies all three and it's a shame that the path forward is simply to throw more bodies at a broken solution.
Recently the Erlang Ecosystem Foundation [EEF](https://erlef.org) was founded and supported by a several companies and the community to ensure the Erlang (including Elixir) ecosystem is maintained.
Unfortunately the status quo is not great – rather than doubling down on poorly thought out solutions it would be nice to see actual improvement. I spent enough time dissecting distillery in an attempt to get deployments to work to make my eyes bleed.
Contrast that with rust where the developer experience is front and center. Even as the syntax evolves over time it remains a pleasure to use. rls is flaky but that's such a minor problem in comparison.
For those that don’t know Nubank, they are a Brazilian app/bank/credit card that is the biggest (by employee count) core user of Clojure. They use Clojure and Datomic database for their core products.
Not sure how they are using Elixir, but you can find more about their use of Clojure and Datomic on YouTube. They sponsor/speak at a lot of Clojure conferences.
Seems like it was a straight up acqui-hire. They were happy with the dev-work, processes and stuff they got from hiring them originally and wanted all of it. Or that was my take-away from reading it at least.
That and DateTime sorting using the module api. That’s much nicer! One of the few "oh what the..." bugs I’ve had in Elixir was not realizing that sort defaults to structural sorting. Also it helped make sense why all the Erlang datetime primitives are tules that’s structurally sort correctly.
My personal favorite part of this release is the enhanced diffing in assertions! Now if a pattern match assertion fails in a unit test ExUnit will pretty print the both items in the comparing and color highlight the differences!
ExUnit is a pleasure to work with and one of the best unit testing frameworks I've ever used.
If anyone is wondering who is running Elixir and Phoenix (Elixir's primary web framework) in production I started a podcast recently where I talked to some folks about this.
Episodes range from using it in closed source private internal apps in the medical industry to open source apps dealing with billions of events per month on a single server.
Hopefully others will be willing to share more stories in the future. There's a few more episodes going up in the next couple of weeks for Phoenix specifically.
Could someone with professional experience int Elixir give an overview of what's the ecosystem like?
It's hard to imagine working with such a niche language. How easy is it to find quality libraries? Connectors to external systems? Tooling? Someone to ask when running into problems?
Also, what's the market like for Elixir developers? Did you learn the language on the job? For a specific project? In your spare time?
The Elixir ecosystem is really healthy. You can find almost any package you want on hex (https://hex.pm/). Moreover, because it is built on top of erlang you can seamlessly use any Erlang code (which a lot of Elixir apps use).
You can usually find high-quality libraries with a google search or looking at the number of stars of a hex package. Mix, the build tool is awesome and the language now has out of the box support for creating deployment releases.
> Did you learn the language on the job? For a specific project? In your spare time?
I moved my last startup to Elixir due to some pretty harsh constraints:
1) I was a the sole developer of a complex app
2) It involved real-time chat and WebRTC
3) Most of its users were in SE Asia and it was a freemium model
This meant I needed a highly productive framework and neither Rails or Laravel were great choices from a technical perspective or in terms of server costs. Phoenix Presence was also a major bonus since there are so many edge cases around (chat room) presence that are easy to mess up when users have multiple devices. That specific need pushed me to learn the language, and it was such a great experience that I made it my go-to for all web development.
> How easy is it to find quality libraries?
I've been very pleased with the quality of the libraries. Elixir tends to draw more experienced developers and I don't see as much "resume-driven Github" behavior, though of course some is inevitable. There's also usually a clear choice of library to use for a given goal, which is a huge plus over the JS ecosystem.
There are a lot of useful libraries out there in the Rails and Laravel ecosystems that I wish existed for Elixir, though. Probably the most frustrating thing on the libraries side is the lack of first-party libraries from companies such as Stripe. Many company's API docs generally assume the user is pulling in their first-party Ruby/PHP/Java/JS/Python/etc library and Elixir usually doesn't make the list.
> Tooling?
The tooling was a big step up from what I was used to! Zero complaints there, except a few minor ones if you're running on Windows.
> Someone to ask when running into problems?
I've had hit and miss experiences with the Slack channel, but the forum is pretty much the best Q/A experience I've ever had for technical issues.
> Also, what's the market like for Elixir developers?
It used to be easy to hire them since there were a lot of people who wanted to use it and not so many companies hiring for it. Now, it seems a bit more balanced.
I use Elixir about 30% of my time at work. I feel like 75% of my code/architectural sense comes from studying how the Elixir community does things - the quality of discussion in the forums and issue trackers is amazing and generally packages feel quite comprehensible. It's a breath of fresh air and clarity after React Native and Rails - there are a lot more resources for those two, but I find myself doing a lot more digging through noise.
Learned on the job, I get a little recruiter email about Elixir specifically but there are definitely less companies that use it. There's reasonable chance I'll end up in Go or Clojure for my next position but even if I were to never use Elixir again the learning will have been worth it.
I feel like my experiences are in sharp contrast to many others here.
I love Elixir the language but find myself still having to throughly review new libraries to avoid footguns. In particular with "connectors" -- DB drivers, API clients, basic protocol implementations, etc. And resolving those issues normally means fixing them ourselves, often with a significant refactor to someone else's library. And in turn that's meant some of us having to become fairly proficient with Erlang.
So while I'm optimistic about the future of Elixir there are still some pain points that I think relate directly to the immaturity of the community.
Are many of these issues related more to older Erlang libraries? Most all of the Elixir libraries that aren’t a WIP have been pretty good for me. Just curious which sort of protocols too. Not always, but I do find older Erlang libraries often lack unit testing and consistent doc tooling, likely due to lack of tooling in earlier days.
Probably 50/50 old (but popular) Erlang libraries and newer Elixir libraries.
For protocols, we have a not-uncommon use case for which there’s no mature HTTP client. Mint might be an option but it’s new enough that I haven’t evaluated yet.
It really depends where you're coming from. If you're from the enterprise world I'd expect you'll find the ecosystem limited for anything else than web related, maybe even for enterprise web integrations. If you're coming from something even more niche (for web) like Haskell you'll think the ecosystem is flourishing.
Libraries are generally of good quality and reasonably well documented. The community is very energetic and supportive. Moreover, there's an exceptional range of libraries and solutions available for certain problem domains in which the Erlang platform excels such as distributed concurrency and soft real-time applications in general.
If the problems you work on fall outside of the web sphere Elixir is not a good fit generally.
I can’t agree about the "just web dev" part. After using Elixir extensively in embedded devices it’s been fantastic. Some libraries are lacking, especially scientific. Still I find the time implementing say, polynomial curve fitting, to be more than compensated for by the robustness of the architecture and avoiding the quagmire of OOP code. It’s actually kind of fun to me using Elixir/BEAM for data processing.
Fair enough, I should've put it more general like "distributed computing". Something that does networking stuff and prioritizes low latency instead of high throughput.
I also work in the distributed messaging space and so far my experiments have shown elixir to be able to keep up with our scala stack with the advantages of no thread tuning and much easier debugging. So I'm curious why this keeps popping up.
My point was rather that that's where Elixir excels.
Throughput is always a compromise with latency in garbage collectors and schedulers.
Elixir prioritizes low consistent latency with its garbage collector and preemptive scheduling. Whereas many other systems, such as Haskell's GHC compiler/runtime prioritize high throughput instead for better computational performance.
All the computations have to run inside a process in Elixir. Erlang's platform constrains each process so that any single process cannot hog all the resources available. Therefore, you need to split the computation to many processes when you do CPU intensive work. And processes carry message passing overhead, leading to reduced maximum throughput.
Something like lots of small messages with minimal processing (think: chat) over a bunch of network connections sounds like the ideal sweet spot for Elixir.
Perhaps it’s in reference to compute throughput or disk io? BEAM doesn’t do quite as well in those areas. Not bad but ok. I just did some micro benchmarks on matrex compared to numpy and surprisingly the Elixir nif’s were about 10% faster on my MacBook. Dirty threads have helped nif’s on providing compute throughput too.
I would love to use Elixir for simple non-demanding 2d games. I love the language syntax and i think it will work great for these use cases. Unfortunately, Elixir ecosystem seems to be all about webdev only.
I would say there are at least 4 subgroups that are active in the Elixir community: distributed systems (alongside Erlang), web dev (Phoenix, Plug, etc), data pipelines (GenStage, Broadway, etc), and embedded systems (Nerves, Scenic, etc).
Learned on the job. Previous professional background PHP, JS. Beginner to what I think to be competent ("full stack", a range between infra and clustered prod deployments to page layouts in Phoenix LiveView) in about four months.
I've been able to find high quality Elixir packages without trouble. I haven't had to fall back to Erlang packages for any holes but I feel confident because I could.
A few years back I wanted to try it for a microservice but found it didn't integrate with our system because of missing features in the ZeroMQ libs of the time. So there are and were corners where things aren't fully fleshed out. I imagine you can find these odd corners in most ecosystems.
I've been happy with the libraries I've found and used in general. All the common web stuff seems to be there. ExAws solves most of the cloud integration I've dealt with. But I don't imagine I'd find a selection of high-level, highly ergonomic Google Sheets libraries the way you would in Python. Not yet.
I'd say its still early days but healthy for the job market. I've found freelance work with an Elixir shop recently which is fun. But it is nowhere near Python, JS and all. Still, plenty of people making a living as employees or long-term contractors doing it. And it seems to be growing at a steady rate. I'm hopeful.
Learned it out of interest. Tracked down my current client through the Elixir Slack actually.
As someone casually looking for Elixir opportunities in Paris, France my observation is that there's not a lot of them (expected), and usually come with a RoR requirement (expected as well, I guess).
Also it seems some companies rewrite their Elixir services in Go?
I've made the same observation in Berlin. Not a lot of job offers, and those that exist are more like "yeah, we're also trying out a bit of Elixir in our stack...". Such a shame.
For the elixir programmers who are going to read this: do you use it professionally ? If so, for what purpose ?
I'm interested in learning this language but I don't really know what can be built with it ? It is a general purpose language or a more specialised one ?
General purpose for anything that is long-running. I mean more than a few seconds.
In my case, we use it to power web api, backend systems, databases, IOT devices. Anything that is not a "cli" thing basically. It is not the best for desktop GUI app because it lacks a deep framework for that, but it works well with it if you can make past that hump.
It is not good at:
- smartphone app. That is mostly due to the walled garden that these devices are
- CLI tools
- Systems engineering
- on the fly scripting
- That basically is it
I've been using it professionally for a little over two years as well. At a basic level, it's doing basic API / CRUD pages but, combined with the Phoenix framework, it feels like my time is much more effective (maybe 10% boilerplate, 90% business logic).
On a more advanced level, it also drives websocket communication for our web app, making two-way communication both simple and fast. We also take advantage of its multi-process facilities to drive long running tasks (cron jobs, long-running HTTP requests to slow services, data batching and analysis...) all within the same tool.
It's paid dividends distilling what would otherwise be a complex setup of various tools, each with their own communication interfaces and failure modes, into one simpler system.
Elixir is not "general purpose" like C, Python, or Rust might be, but it doesn't pretend to be. But for writing maintainable, robust, distributed and fault-tolerant systems that do networking, I love it.
2.5 years, a Phoenix webapp. It's the backend of a marketplace for invoices. The frontend is a React SPA. It interfaces a number of third party JSON and SOAP APIs. It's still well within the limits of a medium low server on GCP. No need for fancier environments.
Coming from Rails I like that I don't have to go through separate job handlers, everything we need is in the language. I don't like much ecto (too complicated for our need.) I dislike the configuration, build and deployment process (it's definitely not snappy). By the way, it's great that Phoenix autodetects changes and recompiles them without the need of an IDE.
Compared to another Django project I've been working on in parallel, the Elixir one feels more robust and easier to expand upon. Compared to Rails ones, it's about the same but with less third party libraries.
What I found interesting is the author of Phoenix said in a podcast[0] that most of the apps he deploys don't use releases. They just run things inside of a Docker container using mix straight up.
I know at least one company doing the same. I'm not sure it's a big advantage. Currently we install a server using ansible once (debian, apt-get erlang and elixir.) We run tests on Travis and make it start a build process on a server of us, create a release and deploy it using distillery. Configuration is compiled at build time with secrets installed on the build server. Erlang/Elixir don't play very well together with systemd (not easy to detect if they're running) but what we setup is okayish and keeps us running.
With docker I imagine we still need the build server, secrets would still be there, compilation must be done there before we create the image (mix phx.server on uncompiled sources is going to take minutes and eat up the CPU of the production server.) Then we must push the image to a registry and pull it. Probably docker would interact better with systemd but I never tested it with a BEAM project. Finally we need something to switch connections from the old container to the new one. Distillery takes care of that now.
All summed up I see some pros a cons, both are still cumbersome. Btw, we're on Elixir 1.7. We didn't check yet the new release and configuration features of 1.9. Too busy with new business features. Customer's decision.
I'm not an Elixir expert but doesn't not using releases come with pretty big down sides?
I vaguely remember reading that a release will pre-load all of your modules at boot up time so that by the time the app is running, everything is as optimized as it can be.
But if you use mix without releases then everything is lazily loaded, so unless you had extra code that gets run on deploy to curl all of your endpoints (to warm up the VM) then users would experience slower load times as your app's endpoints were naturally discovered?
It makes me wonder why the creator of Phoenix still decides to not use releases. Unfortunately he didn't go into detail.
We use it at our company for our inventory system. We make hundreds of concurrent http requests per minute and parse json and soap responses that are up to 8 MB in size. We're a tiny team, so while its possible to accomplish this in many tech stacks, functional programming, pattern matching, immutable variables and other Elixir/Erlang features make it easy to release a stable product quickly. This project has been in production for 2.5 years and has been working beautifully.
I've been using Elixir professionally for the last ~5 years on over a dozen projects.
I was originally drawn to it because of its superior support for websockets. It can trivially handle shitzillions* of simultaneous connections and thus make fully realtime, dynamic web applications within reach of small teams of developers. Other languages _can_ do this, but with much more complexity and cost to host and develop.
Currently I'm working on a fintech API that doesn't use websockets :). Elixir is a great choice because its syntax is the perfect balance of being expressive but not dense. I find that describing a solution in my head translates almost perfectly to a series of functions. It's my go-to language for any task outside of scripting.
I'd compare the experience of using Elixir to drinking a glass of lemonade on a warm summer day. Everything seems to happen very easily.
I've been using Elixir for personal projects for the last 2 years; The syntax is refreshing coming from C#/Java world. I learnt so much while learning to program in Elixir especially Pattern matching, functional programming and Actor-model concurrency. Highly recommended
I use it professionally about 90% of the time, and for my own projects almost 100% of the time now. I’ve been in the community for about 6 years and still absolutely love it.
If you want, you can write scripts in it. Just like Python, but that isn't the sweet spot. It is much more suitable for long-running things.
But Nerves is a cool project for Elixir + embedded Linux.
Scenic is a neat project for OpenGL UIs in Elixir.
It can do a lot of different things. You can pick it for the concurrency, the durability or the distributed nature of it. Tons of potential applications. So general purpose-ish. But not as general as some others.
Oh, and the Lumen project is looking to get it to compile to WebAssembly rather than run on a VM which seems like it will also provide a more lightweight way of running it. That both adds a new use-case and potentially improves the places where it can be suitable.
I developed 2 simple web APIs. Built-in caching and background processes simplified development and deployment. The server just needs PostgreSQL and the application release, which is a self-contained deployable artifact. No need for redis, cron or celery...
Now as a team we're developing a more involved application allowing to schedule jobs and services dynamically.
Background processing and real-time updates are among the typical use cases for Elixir/Phoenix.
I used to program professionally in Elixir where we talked to a ton of external providers. So, our app was heavy on the network (http) and Elixir was a really good fit for it. Now, I use it on personal projects.
The "Tracking of compile-time configuration" part definitely stands out here for me. We've been dealing with this using private module functions but this new language approach is cleaner.
DateTime.now! is the same as DateTime.now which existed forever but will throw an exception if it fails rather than return an error tuple. It's good they added it, but not a problem before.
That's why most people use a third party library. For me it's fine for most things, what were you doing? An example of such a library I've used is https://github.com/bitwalker/timex which seems quite complete.
As someone who writes Elixir full-time in a product with deeply complex date / time needs (spanning multiple timezones, sources of time, multiple meanings of 'month', etc), I can say with some conviction that the the simplicity of Elixir's DateTime module is most definitely a feature. The lack of something as transparent in Rails was / is a huge part of what makes our team so productive since porting the product to Elixir; NaiveDateTime alone has saved us from more bugs than I care to think about. Between Elixir core and Timex, they've definitely solved the harder corners of time as well as any other library or platform I've seen.
FWIW, timezone handling was added in v1.8 or v1.9. At this point I think Elixir has ported all features from Timex, except date parsing and date formatting.
I'm actually really happy with it now. At work we used Timex for all the datetime/timezone stuff because, as you say, it wasn't available in earlier versions of Elixir.
However, since 1.9 it's quite good, IMO. I ripped out Timex from most of the code because it's a beast of a library and not especially well documented, relying on just TzData for the TimeZone database. It's great to rely on just the standard library again because it's up to Elixir's usual standards of documentation and stability.
I built an event ticketing site a couple of years ago in Elixir/Phoenix and it has been rock solid since the initial release. The only painful thing during development was datetime storage and math - I used a third party library (I’m not at my development machine so I don’t know which one it was).
The main positive I see is that I can easily navigate through code (due to absence of complex objects/classes) and the standard library seems to be very extensive.
The language was also easy to get into. My only complaint is that the IDE support for intelliJ(through the plugin) hasn't been impressive though I can live with it.