I like Elixir and Erlang. For some Elixir will be an easier and more accessible path toward using Erlang VM (BEAM), which, I think is an outstanding piece of engineering.
Elixir besides looking more familiar has macros and can let you re-assign variables (data structures are still immutable).
Usually I hear complaints about Erlang syntax. My personal opinion is Erlang's syntax is consistent and elegant. I prefer consistent and elegant over "curly braces" but with ambiguity and complexity. Usually it is things like thinking about actors, of functional paradigms (using recursion vs iteration), dealing with distributed nodes that are much interesting and harder. But everyone is different, so for those that syntax itself is a stumbling block, Elixir is an option.
And just to be complete there are also Lisp, Prolog, Lua and basic Python integration all in various stages of maturity:
Another advantage of Erlang's unconventional syntax, as well as its single-binding variables, is that it doesn't look like a typical imperative language. Because of this, I'm not as tempted to think in imperative terms when programming in Erlang. That having been said, I do like Elixir's string-handling functions.
Elixir is awesome. A syntax similar to Ruby, but with all the fault tolerance and scalability of the Erlang virtual machine. So all the cool stuff of Erlang with none of the warts!
To bring it back to a normal Erlang analogy level, the rooms are instances of Erlang VMs. Since Erlang has isolated memory between processes, the only way to ask one process in one virtual machine (reaching it either by its registered name or if you know the pid somehow) for data (i.e. values of variables) is to send messages to it. You can't access variables/data across VMs/processes directly, you have to talk to them.
I suppose I want the example to show how, when I push data through the portal, it appears on the other side. I'm guessing the idomatic way has to do something with registering a function to be called on message/data received on the "other" end. It just feel like the article could/should be extended a bit there, to make it "full circle" so to speak.
What's already there is good, but it leaves me hungry for more, and a little lost as to how to achieve more.
Thanks for the tip on upstream packages for Debian -- I somehow missed the fact that there was a repo for Debian (well, that, and I already had wheezy-backports enabled, and it turned out to work fine with Elixir from source).
There really isn't anything more to it than in Pid1 doing Pid2 ! MyMessage (that is the literal syntax in Erlang). The rest is taken care of by the Erlang VM. How do you figure out Pid2 (on :room2) from Pid1 (on :room1) then? Either substitute it for Pid2Name, which could be :orange for example, or call and RPC function to room2, MySystem.give_me_a_pid() for example.
I don't understand what you are asking here. The example at the beginning of the "Distribution" section shows how to get the value from the door in room1 while running on the node corresponding to room2.
The same way you can call 'Portal.Door.get({:orange, :"room2@COMPUTER-NAME"})' on the first node (the one corresponding to room1).
Hm, I believe that is what I was asking :) I'll have to look when I'm back at my computer with the example code (and and more importantly an elixir install).
Ok, now I see a little more of how things are connected. In my opinion, it would've been nice to be a) more explicit about the naming/aliasing of blue/orange in the final section, and b) Show how to actually read data sent from room2 in room1, eg:
# Start session for room1, shoot orange portal in room1
$ iex --sname room1 --cookie secrit -S mix
iex(room1@COMPUTER-NAME)1> Portal.shoot(:blue)
{:ok, #PID<0.67.0>}
# Start session for room2, shoot orange portal in room2
$ iex --sname room2 --cookie secret -S mix
iex(room2@COMPUTER-NAME)1> Portal.shoot(:orange)
# set up aliases/variables for blue/orange in room2
iex(room2@COMPUTER-NAME)1> blue = {:blue, :"room1@COMPUTER-NAME"}
{:blue, :room1@COMPUTER-NAME}
{:ok, #PID<0.68.0>}
iex(room2@COMPUTER-NAME)3> orange = {:orange, :"room2@COMPUTER-NAME"}
{:orange, :room2@COMPUTER-NAME}
# Use aliases to set up portal transfer in room2
iex(room2@COMPUTER-NAME)4> portal = Portal.transfer(orange, blue, [1,2,3,4])
#Portal<
{:orange, :room2@COMPUTER-NAME} <=> {:blue, :room1@COMPUTER-NAME}
[1, 2, 3, 4] <=> []
iex(room2@COMPUTER-NAME)5> Portal.push_right(portal)
#Portal<
{:orange, :room2@COMPUTER-NAME} <=> {:blue, :room1@COMPUTER-NAME}
[1, 2, 3] <=> [4]
# set up aliases/variables for blue/orange in room1 (saves typing!)
iex(room1@COMPUTER-NAME)2> orange = {:orange, :"room2@COMPUTER-NAME"}
{:orange, :room2@COMPUTER-NAME}
iex(room1@COMPUTER-NAME)3> blue = {:blue, :"room1@COMPUTER-NAME"}
{:blue, :room1@COMPUTER-NAME}
# Anything in the door?
iex(room1@COMPUTER-NAME)4> Portal.Door.get(orange)
[4, 3, 2, 1]
iex(room1@COMPUTER-NAME)5> Portal.Door.get(blue)
[]
#Switch to room2, push a value:
iex(room1@COMPUTER-NAME)6> Portal.Door.get(blue)
[4]
iex(room1@COMPUTER-NAME)7> Portal.Door.get(orange)
[3, 2, 1]
# Verify that we're communicating, in room1:
iex(room1@kuromaki)6> Portal.Door.get(blue)
[4]
iex(room1@kuromaki)7> Portal.Door.get(orange)
[3, 2, 1]
I'm still not entirely clear on if it's possible to access the "portal"
from both rooms [edit: to call push_right from room1 on the portal instantiated in the session in room2] -- could I get at it from room1 by qualifying it with
room2@COMPUTER-NAME? If so what would the implications be? I assume
functions are called via message passing, so this would be safe?
I think a lot of the stuff up to the very last bit is good, I just feel
the article stops a little short. Maybe I just need to read it again
(and play more with elixir).
I love the concept of Elixir, but is it used out in the wild much? A language's popularity, or lack thereof, has little influence on whether I'll learn it or not, but I'm always curious about this.
I use it for some minor automation tasks at work (munging data in files and the like). That's one of the coolest things about Elixir in my opinion; it's great for the kind of stuff you used to use Perl for, while still being fantastic at the kind of stuff Erlang is used for. I'm obviously not using the full power of the language by any means and I'm yet to use all the OTP stuff except for toy applications for fun. But it's a refreshingly enjoyable language to work in. I haven't built anything that a client has directly paid for with Elixir yet, but sooner or later I hope to get something like an Elixir version of one of our Rails apps going in my free time and convince my boss we should give it a try for real.
Currently any large Erlang/OTP production system uses a combination of Erlang for long-living servers and Python/Ruby scripts for the automation/deployment/scrapping/scripting. There are escripts, but they awkward to use.
With Elixir it's easy to do scripting and have much greater code reuse.
I definitely see how this would be useful for automated tasks. I have some python scripts doing a fair bit of automated data munging that would probably benefit from being written in Erlang/Elixir.
Slight tangent - people often say learning Haskell is worth it for the eye opening experience it provides, regardless of whether you get to use it day-to-day. Would you say the same of Erlang and Elixir?
Funny you should ask. I actually started giving an honest go at learning Haskell before I started learning Erlang and later Elixir. So for me, I wouldn't say they were as eye opening as Haskell (truthfully Common Lisp and Scheme gave me more "woah!" moments than anything else so far) simply because of the order in which I learned them.
However, if you've never learned Haskell, OCaml, or F# I don't think it's a stretch to say that Elixir/Erlang's similar use of pattern matching and guards would have an eye opening effect that makes it worth learning. In both Haskell and Elixir/Erlang they're a core part of using the languages idiomatically. Once you see it in action you'd be hard pressed to not take some of the lessons with you elsewhere.
So, yes. Elixir and Erlang will make you rethink some assumptions about how to solve problems you probably never knew you had. Such as the "necessity" of explicit conditional statements. If anything you'll get better at using recursion to solve actual problems instead of just for contrived classroom-type problems.
I can't say explicitly; Haskell is something I keep coming back to playing with but I've never used for any real development, so I can't directly compare them.
With that caveat though, Erlang and Elixir are gentler introductions to FP if you've never experienced one, yes. But I wouldn't describe them as functional programming languages, but rather -concurrent- ones. They -will- change how you think about concurrency, distribution, and fault tolerance if you're coming from a more typical OO paradigm.
Let it crash, and all the mechanisms and decisions made to ensure that that is a viable strategy, the per process encapsulation of state, the message passing paradigm, the extremely cheap concurrency, and yes, the functional aspect of it, have changed my coding patterns in pretty fundamental ways.
To give a real world implication, I had a situation where an unknown number of scheduled tasks had to fire, each one involving multiple steps, with each step being itself a scheduled event (and those times could change). Some could start at the same time. Each one entailed a non-trivial amount of work, IO bound.
The traditional approach would be to create a thread pool of the maximal number of simultaneous things I wanted to support, create a heap or similar of all scheduled tasks, peek at the top of the heap, sleep until that amount of time, then put that task onto the threadpool. Repeat. Any changes though...the heap would have to be rebuilt. Or whatever. A whole lot of bookkeeping, basically, and a data structure that does not map to what I'm doing, and which requires locking, and possible race conditions and bottlenecking.
In Erlang (and Elixir)? A new process per scheduled event, with a paired timer process to send it a message when it's supposed to start up. Each process is responsible for its own timer; updates to a process cause it to modify its timer, and if a task involves multiple time separated steps, it just creates a new timer when it finishes one, to wake it when it's supposed to do the next. There is no interaction between scheduled items, so why should I have to code around dealing with all of them simultaneously? No locks, no race conditions, no bottlenecking. Bugs are pretty much guaranteed to be in the task code itself, rather than in the task scheduling code, and are much easier to track down and solve.
There are a couple companies in the wild using Elixir. Once Elixir hits v1(August is the estimate) it will change less week to week and will be more suitable for production usage.
I recently emailed with a company using it for the back-end of multiplayer video games they make. They seemed to be interested in hiring open minded programmers with Ruby, Python, Erlang, and likely other experience, but didn't seem to expect any actual professional Elixir experience. Just an anecdote of course, but perhaps proof that there is at least a fledgling market for the language!
that's about right. > 3k at peak. it's a simple POST for logging views. not a lot of data in each POST. not sure on EC2 box size. using https://github.com/extend/cowboy and pushing to a 16 server cassandra cluster.
In my limited experience (about 2 weeks) with elixir, that's really the only thing I'm having a hard time with. Problems you encounter (due to the fact that you're learning a New Thing...not any fault of the language itself) aren't super google-able, so there's a lot more struggling.
I understand the googleability is a bit of a chicken and egg problem, but I've really enjoyed the language so far so I'm trying to stick with it and lean a little bit every day. Thanks for all the work you've done.
I'm looking forward to learning Elixir, but expect that it will have no work relevance. I had a look for Go jobs on Brit job sites - three. Great learning experience, both, but the wild is slow to change.
I am kind of a fanboy for this concept and I'm super excited that Jose was willing to contribute a write-up! Elixir is an incredibly exciting language in my opinion, mixing some of the things that attracted me to Python years ago with some extremely powerful tools and capabilities borrowed from Erlang's virtual machine, check it out!
If you're out shopping for a new language to learn, I would recommend giving Elixir as much (or more :)) weight as you might give Go, Rust or Clojure.
Here's a few things that I really like about Elixir:
- There's a ton of great resources already out for learning Elixir. José's article here is a good intro but Elixir's official website has a very in-depth getting started guide[0]. Dave Thomas, the author of Pragmatic Programmer and Programming Ruby (arguably the book that helped Ruby grow pre-Rails), has written a great book titled "Programming Elixir"[1]. Authors at Manning and O'Reilly are also working on Elixir books to the best of my knowledge.
- Elixir ships with a great build tool, task runner and dependency manager named Mix. There is also a package manager already built named Hex[2].
- Elixir compiles directly to Erlang byte code, so you get to not only take advantage of a very mature virtual machine, but you also get direct interoperability with Erlang libraries! This gives Elixir a robust ecosystem of tools and libraries to use right out of the gate so you can be productive.
- I try not to judge a language by its syntax anymore, but I realize that some do. If that's your thing, Elixir has a Ruby-inspired syntax as well as great support for metaprogramming via macros.
- Elixir development is going very fast and the language is stabilizing more and more by the day. If you need the "1.0 stamp of approval", that should only be weeks to a couple months away at most. The community feels very strong for a language this early in the game. The creator of the language, José Valim, is also very fair and considerate when discussing the language.
- The pipe operator lets you take all of your small functions and easily show the flow of how the operations are applied. This is one of the killer features of Elixir for sure and I'm not sure when I'll feel like I've overused it.
- Testing is at the very forefront of Elixir. All projects generated using Mix (the build tool described above) come with a ready to go test runner. You can also embed tests in the documentation of your code and they too will be tested for correctness.
Now, to be fair, here's a couple things to keep in mind when learning Elixir. These might seem like negatives or challenging at first, but they quickly become some of your favorite parts of Elixir:
- Elixir is a functional programming language, so that can be quite different as most of us on HN I feel come from OOP backgrounds. You have to stop thinking in classes, methods and state and start thinking about data structures, functions and immutability. Elixir is dynamic though, so picking it up isn't quite as challenging as learning a functional language and type system at the same time.
- Pattern matching and recursion are going to be at the core of writing expressive systems. Thinking about problems recursively is mind-bending at first but will start to feel natural. Pattern matching will both make you never look at an equals sign the same way again and help you write very easy to understand function bodies.
- OTP and its well thought out patterns are going to be pervasive to your Elixir programs. If you've ever ran into an Erlang zealot, they probably were ranting and raving about how well Erlang scales and handles failure. OTP and the Erlang VM are the secret sauce. How this all gets accomplished will feel very foreign at first (thinking in Supervision trees and message passing) but stick with it.
I've considered Elixir as something worth picking up next, but my question is, why would I chose it over Clojure when Clojure gives me similar functionality (macros, some concurrency), but much deeper library options?
As yohanatan mentions, the OTP ecosystem is build around the notion of letting processes crash. In every other language that I can think of, you try to handle all errors immediately when they happen, whether that be an explicit check like in C or Go, or through some kind of exception system.
In Erlang/Elixir, your programs should be designed such that each process performs a small enough task that if it crashes unexpectedly, you can "recover" by restarting it. This idea is complemented by the shunning of side effects.
If you do it right, you end up writing wildly different programs in erlang/elixir than you would in other languages.
That said, erlang is specialized for a certain kind of problem, and if you're not building large-scale distributed systems, you probably won't as much out of erlang. Clojure is more general purpose.
The concurrency model of Clojure is different than that of Erlang (and Elixir), especially Erlang is easier to scale to many machines (it's actually built right into the language/VM).
But to be honest, I think you should just learn both. Clojure is an interesting language, even if I disagree with some design decisions (no reader macros...), with interesting capabilities and so is Erlang and even more so Elixir, but that's really the end of similarities between them. Error handling, metaprogramming, concurrency and pretty much every other aspect of these languages are different, so learning both is not redundant IMHO in the least.
That's a tough question to answer as Clojure is a really great language and Rich Hickey is someone whose every word I'll read or listen to in a video.
Someone more well-versed in Clojure than I can probably answer this better, but in my opinion:
- Clojure runs on the JVM, so Clojure's concurrency is still sharing memory deep down, whereas Elixir is not.
- I would think Elixir has deeper library options than Clojure due to having interoperability with Erlang. I guess in Clojure you get all the Java libraries too, though.
- While Leiningen is a much better build tool than other JVM build tools, it still reeks of too much configuration. Mix is very, very simple.
- Clojure, for sanity purposes, requires using a very Lisp-specific development environment. Clojure isn't the only language I use so using something like vim-fireplace or Emacs just for Clojure was a bit much for me.
I'm happy to be wrong on any of my points above and again I think both Elixir and Clojure are great.
In my experience Leiningen is so much slower for typical, casual use case than rebar and mix that it was a serious inconvenience. I didn't try to solve it by having something like a deamon always running in a background or something like this though, it's possible that this is already addressed.
> requires using a very Lisp-specific development environment
I'm an Emacs user, so it was very natural for me, but I think it can be a problem for others. On the other hand I hear that there are excellent plugins for widely-used IDEs for Clojure.
Actually, as Clojure is a Lisp, the only thing you really need is an editor which handles sexps well. Emacs Paredit is really great for this: http://emacsrocks.com/e14.html but as long as you get similar functionality you can use anything you want.
Clojure does not give you similar functionality. Read about Erlang and the BEAM VM, and find out for yourself. If you need the unique functionalities there, you'll have your answer.
"Some concurrency" and Erlang-style concurrency are a thousand miles apart. Read this www.erlang.org/download/armstrong_thesis_2003.pdf. No matter which language you are using, this will help you expand your perspective on the subject of building reliable systems.
The differences are more than just in syntax. Elixir is also a standard lib that many enjoy, out-of-the box tooling (even Erlang folks have praised mix, the project manager for Elixir), meta-programming.
For example, this code generates a bunch of functions using some compile-time code execution and a macro: https://github.com/alco/benchfella/blob/2513f85eff3886fdf1b3.... Doing the same in Erlang would involve using some 3rd party tool for code generation or doing the whole thing at runtime, in a more verbose way.
In short, achieving similar development productivity with Erlang would be quite a challenge.
The best version of that test would be done with a tool like QuickCheck, PropEr, or Triq, which would do property-based testing, and allow to get much better coverage and reporting of problem cases.
Edit: I assumed this was a test, turns out it's a benchmark. My bad.
> Dave Thomas, the author of Pragmatic Programmer and Programming Ruby (arguably the book that helped Ruby grow pre-Rails), has written a great book titled "Programming Elixir"
I bought this ebook when it was first released. The level of care Dave has given to it is astounding. I believe he's released at least 10 significant updates to it as the language has evolved.
Maybe he said somewhere on the book's marketing page that he was going to be doing that, but if he did, I missed it. Extremely pleasant surprise.
I guess I'm misinformed on this. The output of compiling Elixir files are .beam files, not .erl files. Maybe the Elixir compiler compiles to Erlang along the way?
I work in the telephony field, and Erlang comes up every other sentence. I have limited experience with that, but Elixir in my opinion makes it far easier to jump in.
I sort of agree with the common argument about OTP needing a rename, but in the end if a developer can't get past a name, he can't get past a lot of other things either.
Yes it is nice language, but why the author did not create a ruby implementation over Beam?
Maybe elixir has extra features than ruby, so why he does not create a superset of ruby?
Try to image all ruby gems that support the feature of Elixir at zero cost, instead
we have a new language new libs...
Ruby semantics wouldn't map to BEAM cleanly. Pervasive immutability, error handling and concurrency constructs are very different between Ruby and Erlang, I don't think trying to bridge the gap would be an easy task.
Elixir besides looking more familiar has macros and can let you re-assign variables (data structures are still immutable).
Usually I hear complaints about Erlang syntax. My personal opinion is Erlang's syntax is consistent and elegant. I prefer consistent and elegant over "curly braces" but with ambiguity and complexity. Usually it is things like thinking about actors, of functional paradigms (using recursion vs iteration), dealing with distributed nodes that are much interesting and harder. But everyone is different, so for those that syntax itself is a stumbling block, Elixir is an option.
And just to be complete there are also Lisp, Prolog, Lua and basic Python integration all in various stages of maturity:
http://lfe.io/
http://joxa.org/
https://github.com/rvirding/luerl
https://github.com/rvirding/erlog
http://erlport.org/docs/python.html (integration with Python not Python implemented in Erlang)