How I Start: Elixir
howistart.org
howistart.org
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:
https://github.com/rvirding/luerl
https://github.com/rvirding/erlog
http://erlport.org/docs/python.html (integration with Python not Python implemented in Erlang)
That's impressive, considering that Erlang and it's standard lib is mostly string agnostic. I need to do my research on Elixir's libraries.
We've got a startup-like environment, without the hassle of trying to find backing or traction.
We get to work with new technology all the time, though we're primarily an Elixir/Ember shop.
If you're located in Austin or interested in relocating, drop a line to: jay.prince@clutchanalytics.com
PS- We are running elixir in production, right now.
I realize the "blue" "channel" is in room1, but shouldn't I be able to inspect/instantiate some form of "portal" handle on both "sides"?
Other than that, great article.
Btw, there's a recent enough erlang in wheezy-backports to play with elixir, for those running conservative desktops, like myself.
Regarding Erlang on Wheezy, I'd recommend the Erlang Solutions repository with pre-built and tested packages: https://www.erlang-solutions.com/downloads/download-erlang-o...
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).
The same way you can call 'Portal.Door.get({:orange, :"room2@COMPUTER-NAME"})' on the first node (the one corresponding to room1).
# 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).
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.
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?
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.
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.
julia> 7e9 / (30.4*24*60*60) / 2
1332.5414230019496The documentation is pretty good though.
If you are running into issues, feel free to post issues to the elixir-talk mailing list or stack overflow. I check those daily (and many others too).
You can also join the #elixir-lang channel on IRC. It is not as fast as having google-able solutions but we will get there!
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.
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.
0 - http://pragprog.com/book/elixir/programming-elixir
1 - http://elixir-lang.org/getting_started/1.html
2 - http://hex.pm
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.
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.
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.
> 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.
The choice is between Erlang's VM and the JVM. The usual reasons apply.
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.
Edit: I assumed this was a test, turns out it's a benchmark. My bad.
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.
No, it compiles to Erlang. Which is then compiled by the Erlang compiler.
I know I can get updates by twitter but feeds are a commodity I'm used to :(
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.
[1] http://www.gar1t.com/blog/erlang-the-movie-ii-the-sequel.htm...