Hacker News new | past | comments | ask | show | jobs | submit login
Towards a better Erlang - The Excitement of Elixir (devintorr.es)
147 points by devinus on Jan 22, 2013 | hide | past | favorite | 35 comments



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.


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.


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

Wondering what exactly are you referring to?


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.)


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.


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.


"Erlang does not provide macros"

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


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.


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


Author here. If Erlang's community is small, Elixir has an even smaller community. Elixir did just recently rise to the #56 most popular language on Github[1] from #57 however, so it's on the rise.

[1]: https://github.com/languages/Elixir


Devin,

Are there any negatives in Elixir that are not present in Erlang?

Thanks for the awesome writeup. These pieces which take current writings and pair them with real-world answers are great.


In five months of working with Elixir, I can only think of one issue I've had that's related to importing Erlang records with functions as a default value. Even then, the issue is being thought about[1] and there's already several workarounds. Issues are resolved quickly and Elixir releases happen often.

[1]: https://github.com/elixir-lang/elixir/issues/554


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.


> 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 ||.


> 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 ;-)


> 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.

Quite right. When criticizing Erlang, I make it a point to always specify Erlang the language and never Erlang the ecosystem.

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

It's trivially easy.

> 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.

Yep, and as soon as frames are in Erlang we can begin utilizing them in Elixir too for things like pattern matching within the hash structure. The great thing about Elixir is that we don't have to wait for the OTP developers to implement features that developers want.


I can't possibly be alone in liking the Erlang syntax...


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


I assure you that you are not. I find the Erlang syntax incredibly simple and elegant. Every solution seems to be just modifying some grand-unified pattern a bit to fit. But, I guess one mans Erlang is another mans APL.


I can sympathize, I found it's simplicity nice at first. But it quickly wears on you as your codebase grows and you have to refactor. You can find seasoned Erlangers complaining about it's peculiarity often, whether they'll admit it's a problem or not.


It has two major flaws:

* When you move code around, you have to pay a lot of attention to the "ant turd tokens": ; , and . or the lack of one in the right places. That is very annoying.

* It's very repetitive at times. Redundancy is great for servers, not so much for code you have to modify. Take this as an example:

https://github.com/erlang/otp/blob/master/lib/stdlib/src/fil...

It's got a lot of things repeated, and you have to play "spot the difference" to read the code and figure out what's going on. That's a fun game for my four year old, not so much when you're working. I like pattern matching, and it seems that with some tweaks, you could extract common bits of code and end up with something more succinct, so that you only write code that regards the actual differences between two code paths, rather than also having to write the same boilerplate over and over. I have been spoiled by Ruby's "don't repeat yourself" mentality.


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.


> 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.


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.


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


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).


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


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


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?


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.


This is correct. That's how Elixir works.


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..


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.


> 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


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.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: