
Towards a better Erlang - The Excitement of Elixir - devinus
http://devintorr.es/blog/2013/01/22/the-excitement-of-elixir/
======
josh2600
Does anyone have a counterpoint to this article about why not to use Elixir?

We're pretty deep into using native erlang for our work so I don't know how
much benefit we'd squeeze out of a switch to Elixir, but this is quite
intriguing.

BTW, thanks so much for the mention. The core of Kazoo is an all Erlang Stack
and we're proud of it (before anyone jumps at me FreeSWITCH is not written in
Erlang but it's also not something we at 2600hz wrote). Building the sorts of
massively scalable infrastructures we want with the uptime requirements we
need would be much harder without the awesome concurrency tools Erlang
provides.

Delighted that people care about these kinds of languages :D.

Disclaimer: I am the Community manager for <http://www.2600hz.com> and the
Kazoo Product.

~~~
nirvana
Yes, there's one reason not to use Elixir that I know of: [Edit: It appears I
might be wrong on this.]

It doesn't fully cover the erlang syntax. There are a few things you can do in
erlang that you can't in elixir.

As I understand it, this will be resolved relatively soon, in an upcoming
release, possibly only in a matter of months.

Elixir and erlang can be mixed pretty easily, so there's no harm in trying a
module in elixir just to see how you like it. Underneath, it's "erlang all the
way down", so you're unlikely to run into problems.

~~~
yrashk
> "It doesn't fully cover the erlang syntax."

Wondering what exactly are you referring to?

~~~
nirvana
I don't know. I'm new to the language, and after doing the "crash course for
erlang developers" and reading the release notes about a month ago, I believe
I read that there wasn't full coverage, and that it was expected in 8.0 (or
maybe 7.4?)

You probably have forgotten more than I know about this language, so I'm just
going to assume I'm mistaken (or was reading something out of date.)

------
saraid216
So... what's the catch? Can someone provide a devil's advocate against picking
up Elixir?

I've been working at learning Erlang, but it's been a challenge and Ruby's
syntax was a first love, so Elixir sounds ideal for me and I'm tempted to try
it. It just... can't be as good as the hype. So I'd like some earnest
objections to Elixir, especially if they're answered objections.

~~~
josevalim
I am Elixir creator. There are a few downsides comparing Elixir today with
Erlang. First, there are all trade-offs related to Elixir being a new
language: we have fewer resources and a smaller community. Fortunately, Elixir
community is growing very active (on IRC) and it is very likely you get some
support on whatever you are tackling. Also, we haven't reached 1.0 yet, which
means backwards incompatible changes may happen, but we do our best to
properly deprecate them first.

Regarding the language features, since Elixir provides a macro system, you can
apply to Elixir some of the same complaints people would apply to Lisp and
meta-programming in general: i.e. people can definitely go overboard and write
code that is hard to read and maintain ("magic"). On the other hand, Erlang
does not provide macros and has a set of restrictions on how your code looks
like (only one module per file, module forms cannot have custom expression,
etc). At the end of the day, it boils down about Elixir giving you more power,
but also requiring more responsibility from you to use it wisely. Some people
prefer to work with a given set of strict rules.

Finally, we also do our best to have a regular and sane syntax (it is
important after all to have sane macro behaviour). However, due to optional
parenthesis, there is some space for ambiguity. Assuming you have a function
named `abs`, `abs + 1` is treated as `abs() + 1` but `abs +1` as `abs(+1)`.
Those cases are very few though and we also warn about them in the guide. It
is one of the trade-offs you pay for having a more convenient syntax most of
the times, so you can write:

    
    
        defmodule Foo do
          def bar do
            1
          end
        end
    

Instead of:

    
    
        defmodule(Foo) do
          def(bar()) do
            1
          end
        end
    

I believe this translates well some of the observations developers tell me
when migrating from Erlang to Elixir.

~~~
klibertp
"Erlang does not provide macros"

I never wrote any myself, but what about parse transformations? Aren't they
essentially non-hygienic macros?

~~~
josevalim
Sorry, I could have expressed myself better.

Erlang does not provide _lisp style_ macros. They provide macros, but they
look more like templates and are limited. For example, a couple days ago I
wanted to write this macro:

    
    
        -define(line(Opts), case lists:keyfind(line, 1, Opts) of
          { line, Value } -> Value;
          false -> 0
        end).
    

I can call this macro as:

    
    
        ?line(SomeOpts)
    

Basically, the compiler will replace ?line by the template defined above. You
cannot manipulate the AST via such macros and they contain severe limitations.
In particular, the example above just works if you use it once per function.
Since variables are not hygienic, after you use ?line once, the variable Value
is going to be bound and it will be considered unsafe (because it is defined
in just one of the branches) and your code will fail to compile if you use it
again.

In case you want to manipulate the AST, you can indeed use parse transforms.
But it requires a considerable amount of work to get simple stuff done and
iirc you can just use one per module.

~~~
klibertp
Just minor nitpick: "lisp style macros" are not necessarily hygienic either,
which is why you need (gensym). Not in Scheme, though.

"iirc you can just use one per module"

I happen to use erlando[1] often (it's fun!) and I use both do and cut
transforms all the time. So no, there is no limit to how many parse transforms
you can use in one module.

It's true, however, that writing them is a pain, which is why I never bothered
to write one (just take a look at how the 'do' is implemented) - but I just
accepted this as inevitable cost of not using s-exps as a language syntax.
I'll take a look at how Elixir does it, I'd be very positively surprised if it
manages to get real macros convenient in non-s-exp language :)

[1] <https://github.com/rabbitmq/erlando>

------
rdtsc
This doesn't have to be an "either or" choice. The great thing is both of them
live on the wonderful BEAM VM. They both can take advantage of a completely
concurrent garbage collector and all the other goodies. Some modules can be
written in Erlang some in Elixir.

Elixir it seems very easily can call Erlang functions. I don't know about
vice-versa though.

A lot of things in the article are related to syntax. I agree that single
assignment is not needed for concurrency and the if statement can just return
a nil. This, I argue is a matter of preference. In a large system knowing that
a variable you set could not have changed, makes state management more
explicit, some might see that as a benefit.

Also if statements are actually expressions, they should return a value.
Choosing a default value of nil seems arbitrary. Just add another clause to
if. Besides you'd probably want to use 'case ... of' anyway in most place.
Just because 'if' in Erlang matches with the same keyword from C, doesn't mean
that both work exactly the same way.

Now with the records, yes, there has been talk about adding "frames" (the
equivalent of dictionaries or hash tables in other languages). The developers
are thinking about it and I believe in release after the next or the one after
that we might see that.

Now one thing I am really excited about in Elixir is macros. The ability to
create a DSL. That is what probably will get to start playing with it.

~~~
josevalim
> This doesn't have to be and "either one choice". The great think is both of
> them live on the wonderful BEAM VM. They both can take advantage of a
> completely concurrent garbage collector and all the other goodies. Some
> modules can be written in Erlang some in Elixir.

Indeed!

> Elixir it seems very easily can call Erlang functions. I don't know about
> vice-versa though.

Vice-versa is also true. :)

Given you have an Elixir module called String, you can it from Erlang as:

    
    
        'Elixir-String':upcase(<<"fin">>)
    

I agree 'Elixir-String' is not the prettiest sight but this is because Erlang
had an experimental feature called packages that forbade us from using
'Elixir.String'. Luckily, this "feature" is being removed from R16 and in the
future you should be able to simply call 'Elixir.String'. There is more
information about integration with Erlang in the crash course:

<http://elixir-lang.org/crash-course.html>

> Choosing a default value of nil seems arbitrary.

nil would be an arbitrary choice if you look only at 'if'. But if the language
constructs and the standard library consistently uses nil, it is coherent. In
Erlang, not having a matching if raises an error, accessing an unknown key in
process dictionary returns the atom 'undefined' and accessing an unknown key
in a dict returns the atom 'error' or raises an error (depending on the
function you call). In Elixir, they would all return nil. This is extremely
important, because it allows you to create conveniences around nil, like the
operators && and ||.

~~~
rdtsc
> Elixir-String':upcase(<<"fin">>)

Oh great! That is neat.

> This is extremely important, because it allows you to create conveniences
> around nil, like the operators && and ||.

Ok, I understand now. Thanks for explaining.

BTW great work on Elixir. It is shaping up to be a really fantastic language
and BEAM VM is too good not to be shared with other languages ;-)

------
imsofuture
I can't possibly be alone in _liking_ the Erlang syntax...

~~~
Scramblejams
Same here. When I learned it, I expected to have more trouble than I did, and
the syntax just sits nicely with me. Despite all the complaints about when you
use which punctuation, the wart factor seemed a lot lower than all the
bleating complainers prepped me for. Some warts you can't get away from (e.g.
records, though you might use the parse transform du jour), but others you can
(e.g. if? Who uses if? Just use case!).

Elixir looks nice, but for now I've got my eye on Joxa[1] instead.

Anyway, lots of people worry about learning this syntax or that syntax. In
this particular case, they should worry less about learning syntax and more
about learning OTP, because once you get past lightweight message-passing
concurrency and immutability, OTP's where most of the power lies for building
a robust system.

[1] <http://joxa.org>

------
jallmann
Elixir looks interesting, but the issues it addresses in Erlang are mostly
superficial and subject to taste; eg I like single-assignment, and consider
'nil' a deficiency that can usually be avoided with proper typing. But each to
his own -- Erlang does have its quirks, but for me, that mostly fades once
you're neck-deep in code.

I'd like to see a BEAM-based language designed with an eye towards advancing
the tenet of fault-tolerance in ways Erlang currently can't. Probably the most
significant weakness right now is with the type system -- lacking exhaustive
checks for pattern and function matching always makes me nervous, since that's
probably the most common source of errors in my Erlang code.

Rust looks promising in this regard. If a best-practices framework emerges
a'la OTP, Rust is going to be the dream love-child of ML, C and Erlang.

~~~
devinus
> Elixir looks interesting, but the issues it addresses in Erlang are mostly
> superficial.

Perhaps if you also view the issues Clojure addresses in Java to be mostly
superficial, but I have to politely disagree.

> The language has its quirks, but that mostly fades once you're neck-deep in
> code.

Respectfully, I would argue that the quirks aren't made apparent _until_
you're neck-deep in code. That's when it really becomes painful.

~~~
rlander
What? Yes, Elixir's syntax is different, but it retains most of Erlang's
semantics. And it's not hard to see that Clojure and Java are _very_ different
beasts, both syntactically and semantically.

~~~
devinus
I'm reminded of a talk by Rich Hickey in which he recounts his experiences
trying to initially make Java more immutable. He concluded that while it was
certainly possible, it was less than ideal and that a language such as Clojure
facilitated expressing the semantics he wanted to convey. As a thought
exercise, I would have you re-implement Spawngrid's mimetypes[1] library in
Elixir to better understand what I mean. Email me at devin@devintorr.es and I
can further elucidate.

[1]: <https://github.com/spawngrid/mimetypes>

~~~
yrashk
mimetypes author & maintainer here. If I would ever have a tiny bit more time,
I'd rewrite mimetypes in elixir in an instant. The solution we ended up doing
in mimetypes, was the greatest fit for Elixir, not so much for Erlang
(although, certainly possible — and it is being used by lots of Erlang
developers).

------
kriro
Yeah I'm monitoring them. Seems like a good bet that Elixir will be my
language of choice down the road. Some great people behind it, I have a
feeling once Dynamo gets a bit more mature (2013 is their year) the language
will take off.

This video is a nice intro imo (~50 minutes): <http://vimeo.com/53221562>

~~~
devinus
Developing on Dynamo is already a blessing compared to other Erlang web
frameworks[1]. My benchmarking has put simple Dynamo apps on par with
barebones Cowboy which isn't surprising given that Dynamo uses Cowboy under
the hood.

[1]: <http://i.imgur.com/YyAVw1D.png>

------
ryeguy
I can't quite grasp how elixir works with immutability. I have used erlang and
am familiar with how it works. In elixir, is it saying that if I create a
record and store it in variable "a", I can later set "a=3", but I am unable to
change the record once it's created?

~~~
tikhonj
My understanding is that you can't set the variable per se. Rather, you can
only bind a new variable with the same name, shadowing the old binding. This
is very similar to how let bindings work in other languages like OCaml and
Scheme.

So changing a is more akin to creating a new scope with a new value bound to a
rather than mutating a. However, I should be clear that I'm just inferring
this from how let statements work in other languages--I've never actually used
Elixir.

~~~
josevalim
This is correct. That's how Elixir works.

------
minikomi
Is elixir strong enough to learn on its own, or should it be thought of in a
Coffeeacript frame of mind - where learning the underlying Erlang is pretty
much required..

~~~
klibertp
It's an important question - I don't know myself, because I don't know Elixir
and I'm not even sure if I want to learn it (I _like_ Erlang syntax...) but
I'd like to know this too.

My quick guess is that no matter how much work goes into Elixir it is not
going to replace all the libs written for Erlang, in Erlang - and so basic
knowledge of Erlang is still needed to use Elixir to it's full capabilities,
even if just for reading Erlang docs.

~~~
josevalim
> My quick guess is that no matter how much work goes into Elixir it is not
> going to replace all the libs written for Erlang, in Erlang - and so basic
> knowledge of Erlang is still needed to use Elixir to it's full capabilities,
> even if just for reading Erlang docs.

This is correct.

Syntax wise, you can learn about Elixir and not worry about learning Erlang
syntax at all. However Erlang ships with OTP which, as the blog post says, is
a design methodology and a set of libraries for building robust systems.

Elixir does not intend to replace OTP (at all). For example, the next Elixir
version that will ship in a week contains docs and guides on how to write OTP
applications. We explain most of the Erlang API required to do so, but
eventually you will want to call OTP modules and read their docs, for example:

<http://www.erlang.org/doc/man/application.html>

Keep in mind that calling Erlang modules from Elixir is straight-forward and I
believe you will find reading the docs too. You mostly need to know how the
literals look like, for example:

    
    
        What      | Elixir     | Erlang
        atoms     | :foo       | foo
        modules   | Foo        | foo
        variables | foo        | Foo
        tuples    | { 1, 2 }   | { 1, 2 }
        lists     | [1, 2]     | [1, 2]
        binaries  | << 1, 2 >> | << 1, 2 >>
    

You can find more information in the Elixir/Erlang crash course:

<http://elixir-lang.org/crash-course.html>

------
lucian1900
Small nitpick: Clojure's macros are not hygienic. For better or for worse,
this was a conscious decision.

If anything, Elixir's macros look more like Scheme's syntax-case, Rust's
macros or sweet.js.

