Elixir v1.3 released
elixir-lang.org
elixir-lang.org
It is essentially a big pile of macros, so sometimes number of keywords that you have to keep in your head is staggering. Also, Elixir is a pretty big language - I knew Erlang before diving into it - so the barrier and number of concepts that you have to get familiar with is huge. Don't get me wrong - all these concepts/design patterns are necessary (I am thinking about BEAM and OTP here). Erlang (and therefore Elixir) is complete as development environment, that's where the amount of knowledge is coming from.
Cool intro to erlang/BEAM: http://www.slideshare.net/BrianTroutwine1/erlang-lfe-elixir-...
When reading (and reviewing) code, sometimes you can't logically follow what's going on since most of the code is hidden behind macros.
It's ok if I'm on my IDE that helps expand macros to quickly check the flow, but when it's on a webpage or in a gist somewhere, you're on your own.
Sort of like Rails was big on testing, which was generally a win.
There are a few exceptions where there are very large projects that make heavy use of macros (Phoenix's router, Ecto), but they are by far the exception. Most of the macros you use every day are simple ones.
In any case, just wanted to chime in with my two-cents. I've been working in Elixir for the last couple of years and have never felt like I've been bitten by macros. Elixir is certainly a bigger language than Erlang, but many of the things Elixir adds on top of Erlang are what make it so pleasant to work with. For example, the reduction in boilerplate for gen_servers which is made possible with `use GenServer` in Elixir.
Hard to grasps at first - later it is a huge benefit.
Compared to? Perspective matters a lot. It is definitely bigger than Erlang but I would still classify it as considerably smaller than languages like Scala and C++ and still smaller than Ruby and Python.
> It is essentially a big pile of macros
Since "a big pile of macros" is not quantifiable in anyway, I have decided to check for macros and function definitions in Elixir source and I got 1687 functions and 169 macros throughout the whole standard library. It is roughly 10%.
The Kernel module (imported by default) has 60 functions, 78 macros, which is, for example, considerably smaller than Haskell's prelude (about 300 last time I checked?).
Considering things like `defmodule`, `def`, `defp`, `case`, `&&`, `in` are regular macros in Elixir instead of syntax keywords (as they would be in many languages), I wouldn't personally call it a big pile. Although I agree that's a matter of perspective and that's why I decided to measure it).
> the barrier and number of concepts that you have to get familiar with is huge
I definitely agree with this. There are functional aspects, like pattern matching and immutability, the concurrency aspects and the OTP bits. There is definitely a learning curve although most patterns, as you said, are necessary for building the kind of systems Erlang/Elixir enable you to.
That's why a pasted http://www.slideshare.net/BrianTroutwine1/erlang-lfe-elixir-... - slide 96 (I can't find a direct link). Elixir sits above golang but way below Java or C++. Maintainers are doing pretty good work at simplifying things as language matures - for example merging Dicts and Maps together.
> I wouldn't personally call it a big pile.
Touche.
And the argument that "the community discourages macros" isn't particularly compelling, but for whatever reason it has worked well. People seem to use them rarely, and when they are used they're reasonably straight forward. I've been using elixir for a couple years now, and I haven't run into many cases where macros ended up confusing me as a reader.
On the contrary, I stumble over the more esoteric "discouraged by the community" features in scala literally every day.
Relying on the community to exercise restraint with the powerful parts of the language is a huge gamble, but it has worked well in the elixir community.
Sometimes I find that having a detailed blog post about the subject with supporting links and documents can be a fantastic resource for transition discussions.
My team has made the decision to move toward all greenfield projects being started in Elixir/Phoenix and we couldn't be happier. We have been a Rails shop for six years prior.
Is it hard to find developers familiar with elixir/phoenix? Or is hiring RoR developers and training them to work on elixir/phoenix a better option than specifically hiring people familiar with elixir/phoenix?
Just curious to learn about your experience, as there is not much data available on hiring elixir/phoenix devs.
However, this does not make expert Elixir or Phoenix devs. Reading up and learning about OTP and how concurrency works in Elixir/Erlang is necessary to continue to advance.
or
We're busy rewriting a part of our Rails app (that we are having difficulty scaling in Elixir)
I assume the former, based on context, but like they say... you can't put too much water in a nuclear reactor.
* Pattern matching in Elixir is superior to Scala's in every way possible (You can pattern match on function parameters!!)
* Async code is a breeze with Task.async()/Task.await() instead of mapping on Future's everywhere and making sure you have the proper implicit globals imported
* Actor pattern is built into the language and it's a breeze to work with. No need to rely on Akka to replicate it
* JSON is a joy to work with
* Documentation is fantastic in the core language and many libraries
* No more JVM!
* Building a release is much easier than dealing with SBT
If you have a functional background, I would recommend reading Elixir in Action as a starting point. It already assumes you have an FP background and takes you into more of the core features of the language. I really enjoyed it and the content is superb.
You're just trading one VM for another, though. How does having a Beam VM environment differ from a JVM environment?
BEAM has many great advantages such as fault tolerance and multi-node distribution built in. This allows concurrency to be a first-class citizen for applications running on the BEAM. I'm not saying that concurrency can't be done on the JVM, but that I've found it to be much simpler using BEAM. On the other hand, the JVM excels at computational work compared to the BEAM. Both VMs have their place and can be better at different types of problems comparatively.
How? Can you provide a link about this?
@compile [:native, {:hipe, [:verbose, :o3]}]
:-o
But it doesn't produce a native binary, does it?
Is using HiPE a standard practice in the Erlang/Elixir community? What is the quantitative performance gain?
I just discovered about HiPE as well, and I just gave it a try with a simple fibonacci module. Running fibonacci(40) went from 3.9s BEAM to 0.7s HiPE.
I know it's a silly test, but it's pretty sweet to witness such a massive difference out of the box. :)
I won't say testing HiPE with fibonacci is silly because this is exactly the kind of numerical computation where we expect HiPE to be useful: it looks like it is :-)
What sorts of scales are you talking about when you refer to "computational work"?
Also, was/were the comparison(s) you're referring to being done using native code?
On the other hand, the Java/JVM ecosystem is much larger, so there's a serious trade-off there.
You can learn more about BEAM here: https://www.youtube.com/watch?v=_Pwlvy3zz9M&feature=youtu.be http://www.erlang-factory.com/upload/presentations/708/Hitch...
For example, BEAM puts the process call stack on the heap, so you don't need to tune them separately. You won't hit a stack overflow, you'll just run out of memory.
Many, many characteristics like that exist. I prefer a working slow system over a broken system, but I fully understand the preference for loud failures.
* Immutable data. This ties into "functional" section below but it is worth mentioning separately. The benefit here is it is a better fit for concurrency and correctness.
* Lightweight processes. Can have millions of them. But they don't share the heap so act like OS processes in that respect. That means 2 things:
1) It changes the way you think and solve concurrent problems. It reduces impedance between real life problems and how they are solved. Spawning a new process for each long lived connection is obvious and easy.
2) Fault tolerance. Having one request not crash the whole server is a really a massive improvement. In C++ or Java you don't know if something got messed up because of a crash. Maybe some shared data structure or lock got left in an inconsistent state. There is just no guarantee.
* Hot code loading. This is not just a gimmick but it works. Most places don't use it to update regularly and I don't either. But used it a few times in production to add extra logging, fix a customer specific issue without shutting down the cluster before the fix was released. All the while there were 100k/sec requests pounding it. That is plain old money in the pocket. No downtime, no headaches.
* Tracing. BEAM has very good tracing support. When debugging I am quite fond of just logging into a node and using tracing instead of print or log statements.
* Functional. This is more about Erlang the language, and it kind of goes with immutable data. But because of that it means state is more visible and explicit. Looking at a piece of code on a page, I get more context of what is happening because State is passed, updated and returned. As opposed to being some "this" reference which at that point in the code, I don't have any idea how it was modified or what it has in it.
* Garbage collection. BEAM has excellent garbage collection. It is pause-less, in the sense that GC of one process won't block the world. Java has lots of tweaks for that but it is not a default state of affairs.
Welp, this is just a quick list off the top of my head.
At the end of the day, one can probably go through the above list and say I can do all that in Assembly or C. Which is true. BEAM is written in C in large part. To get fault tolerance, can just spawn OS processes in any language. To get immutability, can just go to Github and find an immutable collections library for Python or Java. Java can also do some code loading. But the difference is, it all comes in a single package ready to use. That is huge and I see it as a great benefit.
You can use https://github.com/scala/async for async/await in Scala. It's super easy.
Also, you can pattern match function parameters in Scal using PartialFunction `case` syntax.
which can serve as documentation and are used by a tool called Dialyzer during the build process to find errors based on the type specs.
I have not used this particular tooling first hand, but my sense is that it is well-integrated and works well. Someone else will probably comment with first-hand experience.
The Elixir compiler seems to catch a lot of errors, for what it's worth. If you attempt to call a function that doesn't exist or with the wrong arity, you're going to get an error (even w/o any type specs). The number of compiler errors one has in a statically typed language that are really just about types may not be that many.
w/r/t static vs dynamic, in general, these are the things I'd consider (if you haven't already): you're domain (are you building a rocket or a consumer-facing web app), you're appetite for testing, size of project, size of team, specifics of the tooling w/r/t refactoring (elixir's compiler is pretty good for supporting a big rename, for example; ruby, without a compiler and with so many language features, not so much), how the language makes you feel when you use it (dynamic wins here in general for me; I don't like to be in trouble or interrupted when I'm thinking), the collections library (this is big for me -- I could never go back to a weak collections library -- Go, I'm looking at you), Etc. YMMV, qualifier, qualifier. In general, the specifics really matter -- both of what you're doing and the specific tooling and how they interact.
Elixir seems to strike a very nice balance of all these things with a just right, small, extremely powerful feature set on a rock solid VM with astounding concurrency and distributed computing facilities, if you need them. By all means, I would try it.
Personally, when I used Dialyzer in Erlang, I was underwhelmed by the amount of errors Dialyzer caught (type checking concurrent code is hard, who knew?) — however, it is certainly better than nothing. Plus, the type specifications you have to annotate your functions with help with documentation :)
Reading about Elixir is cool sometimes, but then I look at Dotty, and I feel confident that I made the correct choice.
I've also been keeping an eye on Crystal (statically typed Ruby-esque language, LLVM), but they aren't making great PLT choices so far. Maybe they'll get it together later. Scala-Native will blow it out of the water most likely anyways.
Sort of the opposite of losing statically typed programming, but I've really enjoyed the journey and it's improved my work a lot more than I thought it would. I know Ruby pretty well and I used to feel really dumb all the time when things would break, and it took some time for me to realize that it was a language problem. Looking back and reading some of the Ruby that I ported, it was impossible to reason about, and very difficult to make guarantees for. Nothing was solid at all, and runtime errors could hypotehtically stop the show at any time. With Scala there's a much sharper baseline of what will definitely work or not work.
Types make a LOT of things so much easier, in exchange for making a few things SLIGHTLY more tedious. After doing it, I'd make that trade ten more times if I had to.
But even with a JIT compiler, LLVM doesn't provide the kind of runtime services (e.g., memory and resource management) that we would typically associate with a VM runtime like the JVM's. Like their Web site says, "Despite its name, LLVM has little to do with traditional virtual machines, though it does provide helpful libraries that can be used to build them."
Where does this impression come from? The BEAM VM is maintained by Ericsson, we get new "major" releases every year. In the last years we got the maps data type, the new scalable timer API, better tracing facilities, dirty schedulers, and so on. Lately, at ElixirConf Berlin, we heard about the current efforts on scaling the Erlang Distribution to thousands of nodes out of the box (it is already possibly today, just not by default).
They are also plenty of research projects, mostly in Europe, about improving the VM, development experience and scalability in different ways, such as http://release-project.eu/, http://www.prowessproject.eu/ and http://paraphrase-ict.eu/. That's not including the usual suspects like Chalmers and Uppsala in Sweden, which have been exploring different aspects, specially in the testing area with property-based testing, concolic testing, systematic concurrent testing, etc.
Companies like Adapteva (behind Parallella), Basho, Erlang Solutions, Plataformatec, and many more are investing in the ecosystem too. If there is one thing I am not worried about is the VM and the runtime bright future.
In my opinion, the simple fact we have a runtime with preemptive light-weight processes from the ground-up (instead of tackled on top as a library/framework) with per process garbage collection and inter-node communication taken care of is enough to hold the VM for the next handful of years, even if all development ceased today.
That means being chained to JVM. That is a big downside for me.
So yeah, no.
Is Scala Native used widely? They just finished implementing java.lang.String 20 days ago or so. At least Erlang on Xen has been serving web pages for a few years now: http://erlangonxen.org
But most usage of Scala is on JVM still, wouldn't you agree? We are not talking CPython/Jython/PyPy/Numba... I don't know, the claim that Scala is widely implemented on other platforms while Elixir is tied to BEAM doesn't quite go far for me.
Scala Native is not very far along compared to Scala.js, but it is actively being improved, and is considered an official extension. Additionally, Dotty will bring huge improvements for JVM scala.
I am not super happy with JVM most days, but I'd far and away prefer to be chained to JVM than BEAM. I mean, it's not even a question at this point, considering the billions of dollars spent developing JVM and the work of the brightest minds of several generations. Joe is a cool guy and all, but Erlang is objectively a niche platform compared to JVM.
I found this quote very telling:
> "Elixir is simply the first language since Ruby to really care about code beauty and UX of the language, libraries and ecosystem."
(found here: http://ruby2elixir.github.io/posts/2015/12-29-what-makes-eli... )
(Of course they meant 'Python' instead of 'Ruby' but hey ;-) )
I think the huge extent of macros in Elixir is used extremely dangerously, and it can be very difficult to truly know what's going on behind the scenes sometimes.
That being said, I still prefer Elixir to Erlang for 2 reasons really.
1) I have a very iterative development style which involves a lot of refactoring and test -> code -> test -> code cycles that kept getting extremely frustrating with the ant-turd line endings. Honestly, if I could not have to deal with those line endings I probably would be more inclined to Erlang over Elixir
2) The testing infrastructure seemed much easier to use in Elixir than Erlang.
That being said, I don't see a purpose for Elixir or Erlang in the web serving space, and instead are using it for distributed (and non) stateful servers.
Well, no, Python is four years older than Ruby, so the quote isn't inaccurate :P
I've made the switch from Ruby to Python, mostly for the scipy/numpy/pandas/jupyter support (and performance) - but I don't think I'll ever get away from the feeling with Python that I have to look up how to do things that felt natural in Ruby.
That said, Ruby has gotten more difficult to read, for me, over the years. I just did a small-ish project in Ruby for a client, and was surprised at how much new syntax there is. It has become a large language, in the way that Perl is a large language. It took me longer than I expected to wrap my head around new idioms. Python 3 code seems simpler than Python 2. Ruby 2.x code seems more complex than Ruby 1.x. That actually surprised me, because the first time I tried Ruby (way back when DHH released the first "make a blog in 3.4 seconds" or whatever that RoR intro video was) I found it immediately intuitive, moreso than Python, which I was using at work.
Anyway, my point is that these are big, old, mature languages, with a lot of weird stuff that's made its way into them. It takes time to master something with such depth. It doesn't necessarily mean the language is worse than a new language that is extremely simple...Ruby, Python, and Perl started out simple (even simplistic); the needs of their users caused them to expand. It takes a real effort, and a willingness to break backward compatibility, to stay simple through decades of development. Python 3 made some of those hard choices and got a little simpler; Ruby and Perl haven't (though Ruby and Perl are still stronger languages than they were when they were "simple"/"easy", whatever).
But, I'm also using Python more lately because of the scientific and machine learning stuff, which is a super strong ecosystem.
I have to say that learning and using Elixir has been more pleasant than any other language I have ever worked with. Code is easy to follow due to the functional nature of the language, and the community is one of the best out there.
The applications I've written and deployed have been more stable and fault-tolerant than anything else I've ever done, and I've yet to have any performance issues with the language in production.
Snide aside, it's not this mystical technical panacea. As for community... it has had a large upswell of Rails developers... for better and for worse.
That said, I've had a wonderful experience with all the places I've used Elixir in production or soon to be in production.
My own personal experience doesn't matter much, though, because ultimately Elixir is Erlang and obviously Erlang has been pushed extremely hard in production (Klarna, Heroku, Riot Games, etc.).
Jose Valim and team did an outstanding job being welcoming to new members, emphasizing documentation, friendliness and ease of learning and paying attention to usability. That is no easy feat and requires a lot of hard work and determination, very impressed by it.
Definitely give the Programming Phoenix book a read if you haven't already. The Elixir/Phoenix stack should be ready for most production environments now.
Is there a different name for this concept used in Elixir/Erlang world?
[0] http://pages.plataformatec.com.br/ebook-whats-new-in-ecto-2-...
Come for concurrency, stay for metaprogramming. :-)
hehe. I've only done a bit of Elixir, but coming from a node and Python background that's pretty accurate:
- It should be the VMs job to take care of concurrency, not the programmers
- Although functions having different signatures is common in the front end JS world (mainly due to jQuery) metaprogramming is a nicer way to do it.
Also 5-10ms response times for a basic Phoenix web app is pretty rad. If I wasn't building a startup and thus had the time, I'd love to do more Elixir.
Is there a way to have `mix test` just call --stale steamlessly for me in my terminal?
The other updates to testing in general signal how important testing it to the Elixir core team, and should be a flag letting you know how robust this language and it's tooling is. Take a look for sure, it's a great language.
Search for aliases on this page:
The transition to a functional language is not exactly a cakewalk and I honestly still miss ruby's ability to be able to hack through arrays (no way to easily get the nth element of an array, it's all head|tail recursion) and hashes (nothing like hash[:key]) to make something "work" but the pipe operators and pattern matching are addictive. The eco system is not "opinionated" at all aside from the constraints of erlang. Documentation is crystal clear. Most of the phoenix stack can be used as stand alone libraries/dependencies. There's a lot less magic and most of the "magic" comes from macros which are much more transparent.
I'm honestly excited for web programming again after being burned out on legacy rails app development and deployment. Mix is like gems/bundler/rails {console, server, etc.} in one neat package done right and minus the headaches. Jose Valim and Chris Mc Chord are brilliant but are very approachable and all around nice people to interact with. In my short time with Elixir/Phoenix I'd say the "hype" actually understates the true potential of BEAM for web development and tiny startups. Also there's also LFE (lisp flavoured erlang created by one of the creators of erlang) you can add to the mix (similar to what you have with Scala/Clojure + Java only with concurrency and multicore out of the box with a tiny RAM footprint).
Learning Elixir was one of the best investments of time I've made in learning a new language and made programming a "hobby" again for me. Being able to write a naive implementation/prototype of an app and not dreading a "real" deployment (pulling out a bag of deployment tricks or stringing together a slew if external libraries/dependencies) is the most liberating experience I've had in a long time.
What's wrong with map[:key] ?
Comparing to Ruby: Phoenix promises to be as productive as Rails, but more performant and it keeps the promise if all the libraries you need are already ported to Elixir. Even if not, people consider writing them from scratch.
Comparing to Erlang: Elixir fixes a lot of problems like encoding or inconsistencies in standard library. It introduces many new concepts borrowed from Ruby so it might be a little overwhelming for Erlang developers (Erlang is really small and simple language - the hard part is OTP).
Learning Elixir is like learning to touch type. Initially it slows you down, because you have your habits. You need to learn new abstractions, because old solutions just don't work. After short period you are as productive as before. After a month you can deliver hight quality code quicker which is the ultimate goal of every programmer :) And it magically scales on more machines or at least utilizes all of the cores.
Congrats.
cd /usr/local/src
git clone https://github.com/elixir-lang/elixir.git
cd elixir
git checkout v1.3.0
make clean test
PREFIX=/usr/local/elixir-1.3.0 make install
And then add /usr/local/elixir-1.3.0/bin to your $PATH.I have three specific questions about this:
- Can you make your program executable directly from the command line, by using a shebang and building an executable binary?
- What about the startup time?
- Do you need a lot of "boilerplate", or can you put everything in a single file?
Can anyone who knows both confirm?
https://github.com/boldpoker/edeliver
It handles all the basic things I needed to get an app up and running, and supports hot-code upgrades. It supports multi-host deployments, but I think if you want auto-scaling you'll need to do some more work.
One thing to be aware of is that if you're deploying any NIFs or any native-compiled code, not BEAM, then you can't deploy directly from Mac to Linux servers, you'll need to use VMware or VirtualBox or something to actually do the builds. This includes any packages you use which are using natively-implemented code, which I'm pretty sure includes packages that do password hashing and such.
It is slightly better formatted and contains images from the graph commands and ExUnit diff format.
I recently had to go back to a rails app to do some work and missed some Elixir features already and I've started writing my ruby code in a very elixir way. (well, a functional way).