
Why I Program in Erlang - tel
http://www.evanmiller.org/why-i-program-in-erlang.html
======
mediocregopher
I have used erlang in a number of large projects over the last couple years
and for the most part I'm in agreement with the author about both the benefits
and drawbacks of erlang (when people ask me about erlang I always say "erlang
is great for anything that requires a lot of moving pieces and doesn't require
the code to actually look nice or be readable"). I have a couple of other
drawbacks I think should probably get mentioned:

Logging is..... strange. The recommendation is to use SASL, which writes your
logs in a binary format that only another erlang library can properly read.
SASL has some nice features, like auto-rotation and such, but I'd much rather
have my logs get spit out in plaintext and just logrotate like I do with
everything else. One of these days I'm going to write a proper erlang logger.

Rebar is strange. It's erlang's deployment tool thing, kind of like leinengen
but much less intuitive. I tried getting used to it but found it just made
testing more difficult and made setup a chore. I opted instead to just steal
the makefiles from the mochiweb project and call it a day.

Records have easily the most annoying syntax of any language construct I've
ever used. And god forbid you want nested records, have fun with your full
solid line of selection syntax. Bleh.

Which isn't to say it's all bad, here's some other awesome things about erlang
that I don't see pointed out often:

Polymorphic anonymous functions

The pattern matching is amazing. When I go back to other languages that claim
to support pattern matching it feels like I've lost both your feet and
replaced them with suction cups. There's no pattern matching like erlang
pattern matching.

Hot-swapping of code. Somewhat unintuitive, and has weird behavior in certain
cases, but still definitely better then restarting the server that thousands
of clients have long-running connections on

Records. Their syntax is horrible, but their usefulness is infinite. They're
basically just syntactic sugar on top of tuples that make them easier to
manage and extend.

There's more for both sides, but I'll leave it at that. It's a great language,
I highly recommend everyone take a stab at it. Even if you hate the syntax
it's good exposure to thinking about how to code concurrently.

~~~
yfyf
> erlang is great for anything that requires a lot of moving pieces and
> doesn't require the code to actually look nice or be readable"

Sorry, but this is such a BS claim. Yes, there are bits of Erlang syntax which
are ugly. Yes, you _can_ write absolutely unreadable Erlang code, just like in
any other language. But the whole point is that Erlang is extremely expressive
for the problems in question - distribution and fault tolerance. It allows you
to write code which is multitudes shorter than in (almost) any other language.
Your code ends up being very succinct which is a huge benefit because of
clarity/maintenance/etc.

For some extremely elegant code go look around at basho[1] and 99s[2] code. In
particular, riak_core and cowboy. These are works of art!

[1]: <https://github.com/basho> [2]: <https://github.com/extend>

~~~
davidw
> It allows you to write code which is multitudes shorter than in (almost) any
> other language.

It's not clear if you're making that claim only for 'distribution and fault
tolerance'. In that case, I don't know enough to say. For pretty much anything
else, I'm sure that Erlang is much more verbose than Ruby.

~~~
pessimizer
What makes you sure of that?

~~~
davidw
Having read a lot of Erlang and a lot of Ruby code.

Here are actual numbers:

[http://shootout.alioth.debian.org/u32/benchmark.php?test=all...](http://shootout.alioth.debian.org/u32/benchmark.php?test=all&lang=hipe&lang2=yarv)

Downvoting, by the way, won't change the numbers or the relative verbosity of
Erlang, even if it makes you feel better.

~~~
rdtsc
The "actual numbers" are numbers for a lot of numerical code like computing pi
digits, spectral norms, n-body simulation. That fact that you show those
representative as typical Erlang programs shows that you don't know what
typical Erlang programs are used for or just trolling. (And either one of
those could result in downvoting).

~~~
davidw
I know what Erlang is used for (my name appears in the acknowledgements here:
[http://www.amazon.com/dp/B002L4EXHY/?tag=dedasys-20#reader_B...](http://www.amazon.com/dp/B002L4EXHY/?tag=dedasys-20#reader_B002L4EXHY)
as a reviewer ), and the language shootout is a convenient benchmark site,
nothing more. I never claimed it was anything else, did I?

Ruby isn't exactly a whiz in the number crunching department either: it's
significantly slower than Erlang and certainly not 'meant for that', and yet,
its code is more concise.

If you are saying Erlang is only concise for problems that it was meant for
(and excels at), fair enough.

I'd also say that my preference is for languages that do lots of things pretty
well rather than one thing really well and other things not so great. It's
frustrating in some ways, because for some things Erlang is absolutely
brilliant.

------
tel
I personally have fallen quite significantly out of favor with Erlang. There
are many reasons for which I would absolutely use it---soft realtime being key
---but it is an absolute bear to work with.

Erlang's reliance on spawning processes as a central abstraction conceit leads
to conflating a lot of best practice OTP ceremony with your domain logic. You
end up with a Service Oriented Architecture at the application level---people
rarely write pure libraries, but instead bootable applications that you
communicate to handle needs asynchronously. Additionally, launching processes
is not as simple an interaction as beginner Erlang tutorials have you believe.
Instead, there's a lot of reason to wrap in the OTP boilerplate leading you to
split out things into multiple files and applications.

Dialyzer/Typer is a mess. They're crucial tools for using Erlang successfully,
I believe, but they're also only mildly tied into the language and have weird,
difficult to understand error messages. That said, they're really good at
discovering the myriad errors you'll make passing tuples around.

There's also an enormous amount of black magic surrounding rel creation and
management. Using Rebar and reverse engineering Riak I was able to figure
(most of) it out. It is, as the author states, a very smart system, but it's
also very difficult to get all the pieces firing together.

I would today use Erlang for creating simple, bombproof server architecture.
It's a joy for doing lots of independent, network things in parallel. Mochi
Media seems to be an obvious example, and I remember reading that [forgotten
game name that isn't ROTMG, thanks!] is an MMO game which models every
interacting player as an independent Erlang process. Those examples are both
beautiful, as an infrastructure language I think it's unparalleled and begets
great technology like Riak---I'm seriously itching to use Riak Core sometime.
I just wouldn't want to be the guy who wrote the player logic to run one of
those processes.

(Edit: to qualify, a lot of these flaws are more my own than Erlang's, but
despite spending 3-4 months with it I put it in the box with C as a Right
Knife for the Job kind of language)

~~~
devinus
I highly recommend you check out Elixir (<http://elixir-lang.org/>). We also
now have Relex (<https://github.com/yrashk/relex>) which makes making releases
a breeze.

~~~
tel
I definitely wanted to take a look the whole time I was using Erlang, but kept
feeling like it was more important to really get a handle on Erlang/OTP before
branching out. I imagine it's hard to play in the same waters as OTP's "real,
tested engineering" with a new language, though I definitely support any
language that targets the ERTS.

------
kevingadd
The author mentions how he thinks representing all strings as linked lists is
the 'right thing to do', and later complains about the language's runtime
performance. These two things should immediately seem connected to anyone who
has ever heard the term 'L1 Cache', and it makes me wonder if the author has
heard of it. There are in fact many runtime environments with support for
representing strings as linked lists (I believe V8 and SpiderMonkey both do
this) but it is never a universally correct choice. If you compose a long
string out of a linked list of single character strings your performance will
be miserable.

Then again, when I reached the part where he says "I actually like the fact
that there are not many Erlang libraries available" I started wondering
whether this entire article is a giant troll...

~~~
masklinn
> The author mentions how he thinks representing all strings as linked lists
> is the 'right thing to do'

No. He wasn't talking about strings-as-linked-list there: list concatenation
is O(N) of the first list, not O(1).

OP was talking about Erlang's iolists which are arbitrarily nested lists of
binaries (~bytestrings) and strings (list of integers) which the IO port will
iterate and serialize when it needs to: <http://prog21.dadgum.com/70.html>.
Concatenating two lists (or two binaries, or a list and a binary) by creating
an iolist merely requires allocating 2 cons cells, regardless of the size of
the items being concatenated.

And because you misunderstood this, your whole comment falls down.

> and later complains about the language's runtime performance. These two
> things should immediately seem connected

They aren't and have nothing to do with one another. His complaint is about
the erlang interpreter/VM being fairly slow. Because it is. Not strings being
slow, the interpreter itself.

~~~
lurker14
Point of information for this thread: Erlang's iolist are similar (in data
structure and complexity) to Haskell's bizarrely named Difference List, which
is explained a bit more here:

[http://hackage.haskell.org/packages/archive/dlist/0.4.1/doc/...](http://hackage.haskell.org/packages/archive/dlist/0.4.1/doc/html/Data-
DList.html)

It's basically a tree, which is efficient (amortized O(1) per element) for
many list appends followed by one iteration.

------
fusiongyro
This is one of the most nuanced and gentle pieces of language advocacy I've
seen. We should all be so calm and forthright about our language's
shortcomings.

~~~
sausagefeet
I thought it was a good bit of propaganda combined with lack of understanding
of other languages and failing to give the whole story. I say that has a long
time Erlang developer.

~~~
fusiongyro
Be constructive. Elucidate. I have some experience with Erlang and quite a bit
with many other languages. I'd be curious to hear your side.

------
trustfundbaby
money quote

"Whenever I've wondered about how something in Erlang works, I have never
disappointed in the answer. I almost always leave with the impression that the
designers did the “right thing.” I suppose this is in contrast to Java, which
does the pedantic thing, Perl, which does the kludgy thing, Ruby, which has
two independent implementations of the wrong thing, and C, which doesn't do
anything."

------
maaku
For those who don't know, Evan Miller is the author of Chicago Boss, a Rails-
like web framework for Erlang:

<http://www.chicagoboss.org/>

------
dschiptsov
Talking about Erlang without reading Armstrong's thesis is stupid.

Talking about Erlang after reading the thesis is useless.)

<http://www.erlang.org/download/armstrong_thesis_2003.pdf>

~~~
contr-error
Do you mean that this thesis is the definitive introduction to Erlang or that
it demonstrates a key problem?

In the Adder() example on page 56, is the final line a typo (Adder(10).
resulting in 15)? Should it have been Adder10(10). resulting in 20?

------
davidw
I like Erlang, but the lack of libraries to me just means more things that
other people _have_ already done (for other languages) that I may have to do
myself, rather than taking those pieces, and putting them together to
accomplish something unique and interesting in the real world. I can
appreciate the fun involved in hacking on something for the sheer joy of
writing new and (hopefully) beautiful code, but the business side of my
personality that I am trying to cultivate wants to get shit done, not write
yet another whatever.

Also, this is a decent Erlang rant:

[http://www.unlimitednovelty.com/2011/07/trouble-with-
erlang-...](http://www.unlimitednovelty.com/2011/07/trouble-with-erlang-or-
erlang-is-ghetto.html)

I _do_ like the language, just that it's ... something like a high power
chainsaw rather than a swiss army knife. It does what it does really well, but
cutting the steak you cooked for dinner with it would probably result in a big
mess.

------
nivertech
We built a Distributed Realtime Video and Image Processing Middleware for
Blade and GPU clusters using Erlang/OTP and OpenCL.

You can see the demos here:

<http://youtube.com/clastrsystems>

Unfortunately this is not a large enough market for a startup company.

We building a new exciting product using the same technologies.

------
liancheng
Man, are you serious when you said that "The result is that concatenating two
strings takes O(1) time in Erlang, compared O(N) time in other languages"?
Yes, you are right that Erlang represents strings with lists, and that's the
VERY reason that Erlang must take O(N) time to concatenate two strings (N is
the length of the first string).

Just check your /usr/lib/erlang/lib/stdlib-xxx/src/string.erl, and you'll find
this:

    
    
      concat(S1, S2) -> S1 ++ S2.
    

and "++" is obviously a O(N) operator.

But yes, string concatenation is somewhat faster than other languages that
represent strings with arrays of characters. Because in Erlang, it's O(N),
while in others it's O(N+M), where N is the length of the first string and M
is the length of the second.

~~~
defun
I guess what he was meaning is that in Erlang in most cases you can work with
strings as iolists.

Maybe here you can find a bit better explanation:
[http://erlang.org/pipermail/erlang-
questions/2012-May/066590...](http://erlang.org/pipermail/erlang-
questions/2012-May/066590.html)

~~~
lukego
Right. This is like the POSIX features writev() and 'struct iovec'.
Essentially all of Erlang's binary output primitives are happy to take an
iolist/iovec instead of a plain string and this means fewer concatenations
and/or system calls. Good feature.

~~~
nivertech
iolists map nicely to gather-write writev(), but unfortunately there is no
Erlang primitives for scatter-read readv()

~~~
jlouis
This isn't entirely true, see file:pread/2 for how to do it with a file. We
lack a binary:pread/2 though :)

~~~
nivertech
thanks for pointing it out, looks like it will not work with sockets though.

Also spec says that it will return list of either strings or binaries, not
exactly iolist.

~~~
masklinn
> Also spec says that it will return list of either strings or binaries, not
> exactly iolist.

It's a proper subset of iolists, since it reads from flat data (a file) there
isn't much sense in its adding arbitrary amounts of nesting to it.

------
rdtsc
> the only truly bad news about Erlang is that it is slow. For the server
> applications I have written, the speed of the language has not been an
> issue;

Speed is usually at odds with scalability and fault tolerance. The machinery
that aids both of those things (isolation, sending messages, breaking things
into communicating processes) will take way some from speed.

In the end it is just a trade-off in this particular tool.

------
devinus
If you're interested in getting all the benefits of the Erlang VM and OTP, but
very little of the bad, please check out Elixir (<http://elixir-lang.org/>).

It's staggering how fun and easy it is to code in Elixir while leveraging the
Erlang platform.

~~~
klibertp
But, but... I actually LIKE the syntax of Erlang. It's neat. Consistent. Very
simple. And it's modifiable with parse transformations.

Does Elixir give you anything other than ruby-inspired syntax?

~~~
masklinn
> It's neat. Consistent.

That's quite debatable, ",", ";" and "." definitely have a logic about them
but I wouldn't use "consistent" to describe them. fn/named functions is rather
similar (the syntaxes are rather different).

But the syntax is rather small (if noisy and with more keywords than you'd
expect), which is good. Still, it's no Smalltalk.

~~~
klibertp
It's funny, because I was thinking exactly about ';', ',' and '.' when writing
about consistency. ';' separates clauses - in functions, 'case', 'if' and
'receive' alike. ',' separates expressions - everywhere. And '.' ends
definitions. I find this consistent, but - this being syntax - it's purely
subjective, so it's not like I'm disagreeing with you - I just like it the way
it is.

It's not Smalltalk with it's six (IIRC) syntax constructs nor is it Lisp, but
compared to the syntax of C++ or other rather baroque syntaxes it is simple :)

------
jere
>Erlang does not use a contiguous chunk of memory to represent a sequence of
bytes. Instead, it represents a sequence of bytes as nested lists of non-
contiguous chunks of memory. The result is that concatenating two strings
takes O(1) time in Erlang, compared O(N) time in other languages.

I've often wondered if this was being used anywhere. It seems like such an
easy win, but now I'm curious if it would causes problems with cache misses or
something.

~~~
masklinn
Other commenters have noted that writev(2) is quite similar (although from
reading the man page, it does not seem you can put iovecs inside an iovec, so
there's only one level of nesting)

------
paupino_masano
Warning: I'm not usually overly critical on articles: but this one I can only
think is a little bit of flame bait - a little bit of truth from various
languages turned into fact?

* String concatenation: blatant misinformation. The only reason the _default_ implementation of Strings is slow is because they're made immutable _for a reason_. This if for speed and predicability - if you're wanting to build a String then funnily enough: use a String _Builder_.

* Garbage collection: rubbish. It can run on it's own thread (which can ultimately run on it's own processor). In languages such as Java and .NET the garbage collector has been written so that it collects only what is disposed. Of course you need to be careful about the number of objects your "disposing" (too many can cause the processor to be collecting more than running) but the same is with any language: Erlang included.

* Refactoring... seriously? What happened to compilation errors? Isn't it worse if the structure sends less at _runtime_?

* Data Structures - I'm not sure what he's worked with before, but _modern_ languages allow the transparency he mentions. He mentions "easy to manipulate undocumented data structures" - of course he is asking for trouble there. There are ways around this in OO languages, and worst come worst: roll your own. Don't mess with the internals where you need to "worry about the original author renaming variables ".

I seriously doubt the authors experience in the languages he mentions. Even
so, I doubt his understanding...

~~~
masklinn
> * String concatenation: blatant misinformation.

He was talking about iolists, and he's perfectly correct: an iolist is
O(number of strings to concatenate), you need a single cons cell per element
to concatenate regardless of their size.

> Garbage collection: rubbish. It can run on it's own thread

That adds an enormous amount of complexity to the GC in your generic unsafe
language (java, go, C#, python, what have you), and requires hugely extensive
work on it.

> Of course you need to be careful about the number of objects your
> "disposing"

You completely missed the point, which is that through the VMs design as a set
of heaps (per process) with very little shared memory from Erlang's fairly
simple m&s GC emerges a highly concurrent garbage collector. Not only that,
but short-lived process can be tuned to never trigger a GC pass on their own
heap. Java's concurrent GC strategies are still hit-or-miss and a dark art.

PS: and yes, if you put everything in the same erlang process, the GC
completely breaks down to a pretty shitty M&S.

> * Refactoring... seriously? What happened to compilation errors?

I have no idea what you're trying to say here.

> Data Structures - I'm not sure what he's worked with before, but modern
> languages allow the transparency he mentions.

He listed them, was it really so hard to actually read the post?

~~~
jlouis
Let me add: The _key_ point of the GC per process is that when heaps are
small, pause times are also small. And since GC is counted against a process
reductions frequently GCing processes get swapped out all the time and will
not hurt the latency of other processes.

------
Peaker
"in this way, the performance penalty of garbage collection is amortized, and
so a long-running application will not mysteriously stop responding from time
to time while the garbage collector runs."

I think he meant to say un-amortized? Usually amortization in algorithms means
that we gather up lots of little chunks of work into one big chunk of work.
Here he means that the GC does the exact opposite.

~~~
michael_h
It also means 'gradually reduce a liability in small increments', which I
would assume is how he is using it here. Although, that usage is generally
used in reference to finance.

------
pla3rhat3r
Five9 recently hired Eric Merritt in an effort to take the entire platform and
redesign it using erlang. They are also hiring a lot of Erlang Engineers in
prep for the transition. Hopefully this means the platform will be much more
stable.

------
jpro
Just don't write a database in Erlang.

~~~
jeremiep
CouchDB seems to disagree.

~~~
codewright
More and more of CouchDB gets converted from Erlang to C++ every year since
its creation.

The core runtime and data structures are in C++. At this point, Erlang is
mostly the negotiator between the nodes.

This schism in implementation is partly why I hated CouchDB back in the day.
That and the fact that it's a data Roach Motel.

 _"Data goes in but never comes out"_

------
p0nce
Erlang looks great, but if it's slow is it still a general purpose language?

~~~
jlouis
It is not slow. This is a common misconception.

Erlang is slow, if your problem has a certain structure. Your problem must be
CPU bound. And constant factors _must_ matter. In almost all other cases it is
more capable than most other systems. And the Erlang solution to CPU bound
problems is to punt it to a separate program built for that purpose. Ericsson
has done this for years by pushing CPU bound things into hardware because C is
too slow for what they are doing.

Erlang does, however, target latency over throughput. This means that to the
Erlang system, it is more important to provide low latency than to provide
high throughput. Usually it is very fast, but this choice can in certain
situations hurt throughput.

The primary reason that Erlang is targeting a JITed VM right now is that it
will make it possible to write more of the Erlang VM in Erlang itself, rather
than C. This in effect means that Erlang will be easier to port, so that is a
very good thing.

In my experience, larger systems run extremely fast in Erlang. This is due to
faster development cycles and that you don't have the luxury of optimizing
your C code in larger projects.

~~~
papsosouid
It is fallacious to pretend erlang is slow because otherwise you have to write
bad, unoptimized C code. First of all, unoptimized C is still an order of
magnitude faster than erlang (or more!). Second, there are other languages
besides just erlang and C. For example, compared to erlang I can write the
same thing in haskell instead, have it written faster, have fewer bugs make
their way into production, and have it run faster.

~~~
jlouis
If your C code is doing linear scans over arrays where a dictionary style
lookup is really needed, then there is no way in hell the C code is going to
beat the Erlang code. I've seen this again and again in C programs.

As for your Haskell program, you are right. But you will spend the next 3
months trying to fix memory leaks due to lazy evaluation :)

I think the bottom line, one we can agree on, is that a program written is not
the end of development. It needs maintenance and where certain programming
languages makes it easy to do something, other languages have a harder fare,
and vice versa.

Erlang has a state-of-the-art interpreter. And a runtime written in C. It is
not a slow language if you have a program that spends most of its time waiting
for other things to complete or in the runtime. In fact, that is where it
shines.

That said, don't write CPU-bound jobs where constant factors matter in Erlang.
It is a bad fit for this, because of its interpretation overhead.

~~~
papsosouid
So now we're not just comparing optimized erlang to unoptimized C, but
optimized erlang doing X to unoptimized C doing Y. You can write the wrong
code in erlang too, C does not have any special (mis)features that encourage
doing the wrong thing. It dishonest to say "erlang isn't slow" and use "I can
write slower C code if I do it on purpose" as evidence.

~~~
jlouis
The thing is that "slow" is naturally relative. I hate it when people claim
that a tool is slow. By far the most important factor in getting programs that
work isn't the technology but the mind behind the code. This is true for any
programming language.

I guess the succinct answer is: No, Erlang isn't slow if you know what you are
doing, barring the Caveat about CPU-bound problems. The message I am trying to
convey is that there is more to fast programs than the execution speed of the
technology at hand. It is a factor, admittedly, but it is not the sole factor.

------
nagiek
When he talks about about functional vs. OO-programming, it reminds me of why
I like Drupal.

