
Comparing Elixir and Go - iamd3vil
https://blog.codeship.com/comparing-elixir-go/
======
julienmarie
If you want to really understand the philosophy that makes Erlang ( and Elixir
) beautiful ( and why it made me a better programmer ), this conference by
Greg Young is a kind of eye opener :
[https://vimeo.com/108441214](https://vimeo.com/108441214) .

You realize then that clustering, hot reload, availability etc... are not only
features but the logical consequence of a beautifully crafted environnement
that aims at developer productivity.

I'm sometimes amazed on how easy I can achieve stuff on the Erlang VM that
would take ( if it's not impossible at all ) at least 10 times the time in a
more usual language ( Ruby or PHP when you work in the web industry as I do ).

My last example was when I needed to batch sql inserts in an events database.
In a normal language I would have needed a queue, the libraries for it,
workers, new deployments and infrastructure to monitor, monitoring,
supervision, etc... In Elixir, in 20 lines of code, it's done.

If you do not need complex calculations, the Erlang VM can basically become
most of your architecture. It's already per se a SOA.

~~~
vegabook
how easy is it, even if you _do_ need complex calculations, to get the best of
the Erlang VM and call out to say, Python/Numpy or C when necessary? Can these
external processes still be supervised, for example? Are decent sized matrices
(for example 100x20000 floats so an 8MB data structure) easily movable around
the Erlang VM via message passing?

IE is it viable in your opinion still to use Erlang as a system for
distribution and routing of lots of heavy calculations to many users, if said
calculations are performed outside of BEAM? I am looking at building a
multivariate financial calculation engine, which must be interactive for up to
1000 users, with large firehose of real time data coming in, being massaged,
and then distributed, with the calculation graph being customizable for each
user interactively.

~~~
sasa555
It is possible to start external processes from BEAM and interact with them.
I've blogged a bit about it at
[http://theerlangelist.com/article/outside_elixir](http://theerlangelist.com/article/outside_elixir)

You can also write NIFs (native implemented functions) which run in BEAM
process (see [http://andrealeopardi.com/posts/using-c-from-elixir-with-
nif...](http://andrealeopardi.com/posts/using-c-from-elixir-with-nifs/)). The
latter option should be the last resort though, because it can violate safety
guarantees of BEAM, in particular fault-tolerance and fair scheduling.

So using BEAM facing language as a "controller plane" while resorting to other
languages in special cases is definitely a viable option.

~~~
Callmenorm
I spent 30 minutes looking at NIF, but I was scared away. My understanding is
that if the NIF crashes then BEAM crashes. Which leads me to think that if you
need NIF then you need safety guarantees on the Native side that C can't
provide.

~~~
sasa555
Precisely, which is why I always advise to consider ports first :-)

However, in some situations the overhead of communicating with a port might be
too large, so then you have two options:

    
    
      1. Move more code to another language which you run as a port.
      2. Use a NIF
    

It's hard to generalize, but I'd likely consider option 1 first.

If you go for a NIF, you can try to keep its code as simple as possible which
should reduce the chances of crashing. You can also consider extracting out
the minimum BEAM part which uses the NIF into a separate BEAM node which runs
on the same machine. That will reduce the failure surface if the NIF crashes.

I've also seen people implementing NIFs in Rust for better safety, so that's
another option to consider.

So there are a lot of options, but as I said, NIF would usually be my last
choice precisely for the reason you mention :-)

~~~
vvanders
Aren't dirty NIFs on the horizon as well which help with the whole scheduling
issues currently associated with NIFs?

~~~
sasa555
Dirty schedulers can help with long running NIFs, but they can't help with
e.g. a segfault in a NIF taking down the entire system.

------
haspok
One thing that is completely missing from the Erlang side of the article are
the OOB monitoring and operating capabilities.

An Erlang VM is a living system that has a shell which you can connect to, and
control both the VM and the applications running in it. You can also remotely
connect to another VM, execute arbitrary code, debug, stop processes, start
processes etc. It really is an operating system in itself, that was _designed_
to be that way.

And the best part is that you get all this for free. Whether that is a good
thing depends entirely on your needs. You probably wouldn't want to replace
your bash scripts with Erlang programs :)

What Erlang is not really suited for is where you need multiple levels of
abstraction, such as when implementing complex business logic. You would think
that the functional nature of the language lends itself to that, but then you
quickly realize that because the primary concern of an Erlang engineer is to
keep the system alive, and for that reason you must be able to reason and
follow the code as it is running on the system, all kinds of abstractions are
very much discouraged and considered bad practice (look up "parameterized
modules" for an example of a feature that was _almost_ added to the language
but was discarded in the end).

I think that from this perspective Erlang and Go are actually very similar -
both prefer simplicity over abstractions.

~~~
julienmarie
Totally agree. Erlang is quite against "magic" which improves greatly
readability. Debugging is really straightforward 99.9% of the time.

------
giovannibajo1
I think the part about cooperative/preemptive multitasking isn't saying it
all.

Go multitasking is based on the compiler inserting switchpoints on function
calls and syscall boundaries. But this affects the scheduling of a single OS-
level threads executing that specific goroutine. The number of OS-level
threads that the Go scheduler uses can arbitrarily grow, and OS-level threads
are preemptively multitasked.

So I think the description is focusing a narrow view of the problem. What is
usually required by applications is low latency in reply to system events
(e.g.: data available on network sockets), and Go performs very well in this
context. For instance, the fact that Go is transparently using a epoll/kqueue
based architecture under the hood is probably affecting latency much more than
the whole "cooperative" issue as depicted.

~~~
eternalban
> I think the part about cooperative/preemptive multitasking isn't saying it
> all.

That's still not the entire story:

GC & tight loops in Go:
[https://github.com/golang/go/issues/10958](https://github.com/golang/go/issues/10958)

Per process vs per runtime GC:
[https://news.ycombinator.com/item?id=12043088](https://news.ycombinator.com/item?id=12043088)

~~~
eternalban
Can't update parent.

Please /do not/ read my OP as a dig/boost at any level. Just pure geek
interest in language architectures and sharing info.

------
IanCal
This is more for people looking at erlang/elixir than a critique of the
blogpost or a suggestion for a change.

> Within Elixir, there is no operator overloading, which can seem confusing at
> first if you want to use a + to concatenate two strings. In Elixir you would
> use <> instead.

When this popped up, it reminded me of something people try to do often and
then have issues with performance. You _probably_ do not want to concatenate
strings.

"Yes I do" you'll first think, but actually erlang has a neat commonly used
thing to help here.

Let's say you're doing some templating on a web-page. You want to return
"Welcome back username!". First pass (a while since I wrote erlang so forgive
syntax errors):

    
    
        welcome(Username) -> 
            "Welcome back " ++ Username ++ "!"
    

Now it's going to have to construct each string, then create a new string with
all three. More creation & copying means things get slower.

Instead, many of the functions you'd use to write files or return things over
a connection will let you pass in a _list_ of strings instead.

    
    
        welcome(Username) -> 
            ["Welcome back ", Username, "!"]
    

Now it's not copying things, which is good. But then we want to put the
welcome message into another block with their unread messages.

    
    
        full_greeting(Username) ->
            welcome(Username) ++ unread_messages()
    

More appending than is good here, concatenating lists is going to take time.
Of course, we could put it all in one function, but then we lose re-usability
in the templates and have horrible massive functions. While this is a simple
example, I hope you can picture a larger case where you'd want to split up the
various sections.

Anyway, there's a better way of doing this. The functions that take lists of
strings actually take lists of strings _or other lists_. So we can just do
this:

    
    
        full_greeting(Username) ->
            [welcome(Username), unread_messages()]
    

You can keep going, nesting this as much as you want. This saves a lot of
copying, allows you to split things up and avoids having to keep flattening a
structure.

So, for people about to get started, try not to concatenate your strings, you
can probably save yourself and your computer some time.

For more info on this, you want to search for "IO Lists" or "Deep IO Lists".

~~~
coldtea
> _Now it 's going to have to construct each string, then create a new string
> with all three. More creation & copying means things get slower._

There's nothing about the ++ syntax that makes it necessarily so. The
compiler/interpreter could understand that we're getting a concatenated string
and automatically only create one.

Which is the case in several languages.

~~~
filmor
What is different in Erlang is that strings are a bit messed up in that they
are linked lists of numbers. What you are suggesting (constructing the actual
string in-place) works fine in Erlang, too, but has a bit of a funky syntax:

    
    
        welcome_user(Username) ->
            << <<"Welcome ">>/binary, Username/binary, <<"!">>/binary >>.
    

However, the main advantage of using io_lists instead is that `["Welcome",
Username, "!"]` has constant complexity with regard to the length of
`Username`.

~~~
diamondlovesyou
Note to anyone not already familiar: in Elixir, character strings are all
binaries from the start. Just to avoid the notion that Elixir follows the
mistake of strings-are-linked-lists from Erlang.

------
pmarreck
Go's philosophy around error handling (or lack thereof) is arguably atrocious
compared to BEAM's "Let It Crash (And I'll Just Log It And Restart In 1
Millisecond With Exponential Backoff)" philosophy.

To review: [https://gobyexample.com/errors](https://gobyexample.com/errors)

Manually checking every possible error (and then, only in the spots where _you
can imagine an error occurring_ ) is a heck of a lot of extra work for the
programmer (and code for the code reader/reviewer) and _still_ won't catch all
possible errors (both conceivable and inconceivable) properly. And arguably,
the fact that an unchecked/undetected runtime bug in Go will basically send it
into an "indeterminate state" which is impossible to reason about (much less
debug), is an incredibly strong argument against this philosophy, IMHO. As far
as I'm concerned, as soon as my code goes "off the beaten path" state-wise
(read this as: "significantly differing from my mental model"), it _should_
crash, ASAP. Isn't every bug literally a situation the programmer didn't
account for? Aren't runtime errors _by nature_ unexpected by the programmer?
Why would you then give bugs and errors _even more room_ to corrupt the state
of the world, then? ;)

We are all obsessed with computers and languages when the real limit is the
programmer's mind and ability to reason about the code s/he's building and the
states that code can get into. I think BEAM langs and purely functional langs
more generally (along with functional/immutable data structures, etc.) do a
much better job of addressing this _root_ problem. I'm going to quote John
Carmack from his great blog post about functional programming here
([http://www.gamasutra.com/view/news/169296/Indepth_Functional...](http://www.gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php)):

"My pragmatic summary: A large fraction of the flaws in software development
are due to programmers not fully understanding all the possible states their
code may execute in. In a multithreaded environment, the lack of understanding
and the resulting problems are greatly amplified, almost to the point of panic
if you are paying attention. Programming in a functional style makes the state
presented to your code explicit, which makes it much easier to reason about,
and, in a completely pure system, makes thread race conditions impossible."

~~~
atombender
While I agree wholeheartedly that Erlang's design is better:

To be fair, you can't get Erlang's semantics without also inventing processes
and supervisor trees. And those things would be largely meaningless without
immutability.

Erlang's magic comes from how all the puzzle pieces fit together into a whole:
For example, with immutability comes the ability to always be able to restart
from a known state, and probably greatly simplifies the internal
implementation of the per-process heap.

Those things fundamentally change the language; Go couldn't adopt Erlang's
semantics without eschewing almost everything that makes it "Go".

Error handling is really the least of it. Attempting to replicate some of
Erlang's high-level design principles at a quickly lead to roadblocks. For
example, goroutines cannot be killed; this means it's impossible to fully
implement supervisor trees in Go. It's possible that the runtime could support
this at some point, but it's a big can of worms.

~~~
solidsnack9000
Immutability probably does simplify a lot of things; but it isn't actually
required to get Erlang's model, since Erlang isolates the state of processes
from each other. Each process could have its own isolated mutable state as
opposed to an immutable one and it wouldn't change the "let it crash"
philosophy.

~~~
lobster_johnson
You can't guarantee that isolation without immutabilty, or at least forced
copying.

In Go, it's extremely easy to accidentally send a pointer (or a data structure
that contains a deeply nested pointer somewhere; this includes embedded maps,
slices and channels, which are all reference types) on a channel, which is
bound to break mutability guarantees at some point.

~~~
solidsnack9000
Mutable locals do not necessarily imply pointers...

~~~
lobster_johnson
No, but how do you pass "mutable locals" to other processes? That's the whole
question.

If you pass a "local" on a channel to a different goroutine, Go can't
guarantee to the receiver (which now has it as a "local" variable) that the
sender (which still has it as a "local") won't change it:

    
    
        d := map[string]int{}
        ch <- d
        d["foo"] = 42  // Oops!
    

The only way to do this safely is to to write a channel abstraction which uses
gob or similar to marshal and unmarshal all data, thus copying it and
preventing concurrent mutation, and then always use the channel abstraction.
But always copying tends to be terrible for performance. Erlang is able to do
zero-copy sends to process mailboxes _because_ the data is guaranteed to be
immutable.

Sure, you could instead mandate that senders never hold on to data sent on
channels, but can you ensure this 100% across a codebase contributed to by an
entire team?

~~~
klibertp
> Sure, you could instead mandate that senders never hold on to data sent on
> channels, but can you ensure this 100% across a codebase contributed to by
> an entire team?

Isn't that precisely what Rust is all about?

~~~
lobster_johnson
Pretty much, yes.

------
brightball
Author here. This was published a week earlier than expected so just a heads
up that there are a couple of edits coming.

~~~
jeremyjh
ZeroMQ is a library written in C++, not a server written in Erlang.

~~~
wilsonfiifi
The presence of ZeroMQ in the list of projects built with erlang also made me
frown as well. But in the author's defence, there is a pure erlang
implementation of zeromq [0]

    
    
      [0] https://github.com/zeromq/ezmq

------
d3ckard
That comparison was way better than I was expecting it to be. Go is still on
my to-do list, but Elixir parts seem to be quite thoroughly described and
without major mistakes. I also like the conclusion and to be honest this is
how I always felt about the two. Definetly recommend reading this is if you're
new to any of the two.

------
sahrizv
I think a good way to increase creativity and productivity is to use the right
abstractions of thought and craft. Every good(non leaky) abstraction expands
the creative envelope further and lends itself to creation of new higher order
abstractions for the next generation.

Having coded in imperative languages like Java, Python and C++, I had been on
the lookout for a _practical_ general purpose language which provides good
abstractions/high expressiveness. Elixir appealed to me more than Go in that
regard. It's been six months since I started writing Elixir and it's been a
pleasure.

------
jondubois
I still don't understand what all the hype is about pure functional
programming.

Sometimes mutations are useful. There are lot of good programming design
patterns which depend on mutations.

Also, always copying objects by value every time you call a function seems
very expensive; especially if you're dealing with very large
objects/structs/maps/strings which have to be processed by many functions.

~~~
jondubois
I just had a thought; if arguments always get cloned by value every time they
are passed to a function, doesn't that mean that the time complexity for an
insertion operation in Elixir can never be better than O(n)?

According to this answer [http://stackoverflow.com/questions/11055391/time-
complexity-...](http://stackoverflow.com/questions/11055391/time-complexity-
of-erlang-dict) it claims that for dictionaries it's O(log n). How is that
possible if mutations are not allowed? Wouldn't the function have to process
at least n items? Or it uses parallel processing to get a speedup there?

~~~
owaislone
If you are only dealing with Immutable structures that no one can really
change, there is no point in passing by value. You can always pass by
reference. The language will not allow any code to modify it. Instead a new
variable will have to be assigned if the function changes the values. So, it
can always be pass by reference until a change needs to be made aka copy on
write.

------
EduardoBautista
> It has since expanded into numerous other areas, such as web servers, and
> has achieved nine 9s of availability (31 milliseconds/year of downtime).

I definitely want to read more about this.

~~~
kjksf
This is how myths are created and perpetuated.

This claims from a study of a particular model of Ericsson's ATM switch whose
software was written in Erlang.

A can tell you for sure that: * Ericsson has other switches and other telecom
equipment whose software is written in C++ * other companies (Nokia, Cisco,
Alcatel etc.) also built similar complex telecom equipment whose software was
in C++

I'm going to bet that at least one of those devices was more reliable than
that particular switch, because it's not the language that creates reliability
but people writing and testing the software.

Some languages make it easier than others but attributing some magic qualities
from extrapolating a single case study of a telecom equipment is just silly.

Telecom equipment is reliable because it has to be. If you're incapable of
writing reliable software for telecom equipment then your company will go
bankrupt and be replaced by one that can, even if the language they use is
C++.

~~~
lobster_johnson
But suitability _is_ a huge factor here. The point isn't that "nine nines"
reliability _cannot_ be achieved in C++ or whatever, it's that it's
significantly harder and costlier to achieve.

But also: _Of course_ a language creates reliability. Null pointers are
impossible in Erlang, whereas they are provable impossible to _avoid_ in C++.

So people bring this up because Erlang programs are pretty much reliable by
default (assuming you stick to OTP and its design).

To help it reach insane uptimes, Erlang also has a few features that are hard
to replicate in C++, if not impossible. The main one is hot code replacement;
being able to incrementally upgrade a system in a safe and controlled manner
without restarting it is a huge benefit in such a system.

It's also trivial to attach to a running Erlang program and introspect it as
if you're truly running inside it. Goes hand in hand with hot code
replacement. With C++, you get fairly crummy, low-level things like gdb,
without the ability to actually write C++ code while in the debugger.

Also, remember that crashes can occur in bug-free programs. Hardware failures
can be hard to predict and handle.

~~~
gpderetta
> Null pointers are impossible in Erlang, whereas they are provable impossible
> to avoid in C++.

They are trivially possible to avoid in C++ as you do not have to use raw
pointers. References, value types, custom non-null smart_ptrs, etc.

~~~
lobster_johnson
Not _trivially_ , no. Even if you try to avoid "raw pointers", C++ is an
unsafe language by design, and it's non-trivial to turn it into a verifiably
safe one:

* Even smart pointers are still pointers, which are trivial to access after release by mistake; and references are only safe as long as the caller still exists. C++ does not have anything like Rust's borrow checker.

* C++ threads allow race conditions that can screw up even smart pointers.

* Plenty of libraries (C and C++), which are usually impossible to avoid and completely impractical to vet, will still use raw pointers.

Generally, the word "trivial" and C++ don't go well together.

~~~
gpderetta
Note I was explicitly objecting about null pointers begin impossible to avoid.
My claim is that the C++ type system allow avoiding them just fine.

I'm making no claim about general the memory safety of C++, and its issues are
well known.

------
chx
I am very intrigued in both. I am a reasonably experienced software developer
with about 15 hours a week of availability, anyone wants to contract me? I'd
gain experience with a modern language, you'd get someone on cheaper than
experience would suggest. I know software engineers can use any language but
in reality, if I were to get a full time job at a company which uses either of
these I'd get a lot less money than I am getting now working with Drupal with
10+ years of experience in it. So I would like to gain some real world
experience to make it easier to switch jobs later.

~~~
pdimitar
I feel this deserves its very own thread, because I too would like to do
exactly the same as yourself.

------
sudhirj
> The biggest difference between the two languages is that compilation for the
> destination architecture has to be done on that same architecture. The
> documents include several workarounds for this scenario, but the simplest
> method is to build your release within a Docker container that has the
> destination architecture.

@brightball Go has had first class support for cross compilation for a while
now, no?

~~~
brightball
I need to clarify that I was talking about that being an Elixir limitation.
The previous paragraph talks about Go being able to cross compile no matter
what system it's on but the one you highlighted still doesn't read well.

------
rbosinger
I know people will say "apples to oranges" but this is still exactly what I
wanted to read. Thanks.

~~~
dashoffset
Agreed. It is apples to oranges but the article does an excellent job showing
when/why to use each one. I believe the conclusion was spot on and IMO
combining the stability of Elixir/BEAM with the performance of Go is the best
of both worlds.

------
copyconstruct
There was a good talk at Strangeloop about userland thread runtime scheduling
in both the Go and the Erlang VM.

[https://www.youtube.com/watch?v=8g9fG7cApbc](https://www.youtube.com/watch?v=8g9fG7cApbc)

------
nazri1
The page (like many other pages nowadays) breaks page down - if I press the
page down key I then have to scroll up a few lines because the text are
obscured by the always-visible "FREE SIGNUP" banner at the top.

~~~
manualwise
I'm responsible for this blog. Thanks for the feedback, we'll work on getting
this fixed!

------
aychedee
Really well written comparison that made me, as someone who has used go for a
year, understand a lot more about Elixir.

------
arca_vorago
If I were putting together a new awesome Thing(TM), I think I would probably
use elixir on the front end and internal messaging to handle and distribute
jobs, and let go do the crunching and hard lifting.

~~~
pdimitar
That's the ideal setup really. Golang's concurrency is pretty decent as well
but IMO Erlang/Elixir are much easier, quicker to code in, and more reliable
than anything else I've ever used.

So basically use Golang as a modern C for specialized tasks which require
[almost] the best your hardware can do, and use Erlang/Elixir for everything
else.

------
julio83

        The other trade-off that comes from mutable versus immutable data comes from clustering. With Go, you have the ability to make remote procedure calls very seamlessly if you want to implement them, but because of pointers and shared memory, if you call a method on another box with an argument that references to something on your machine, it can’t be expected to function the same way.
    

I would be happy to know how we can make RPC seamless in GO accross multiple
machines (clustering). I've missed a nice lib?

~~~
buckhx
The stdlib has an RPC package, but there it also has great gRPC support
[http://www.grpc.io/docs/quickstart/go.html](http://www.grpc.io/docs/quickstart/go.html)

------
raulk
Nice writeup! ZeroMQ is not written in Erlang. You probably confused with
RabbitMQ, which is.

------
stcredzero
_In Elixir, error handling is considered “code smell.” I’ll take a second to
let you read that again._

I think that this makes a lot of sense. My experience in just about any
language, is that the official means of error handling already feels like a
code smell, even before you start using it. And if that's not the case, then
it still manages to feel that way when used in a large project.

Lots of Smalltalk projects would actually handle errors by saving the image on
an unhandled exception. For server applications, this was like having a "live"
core dump where the debugger could open up right on the errant stack frame,
and you could perform experiments to aid in debugging.

~~~
digitalzombie
Funny you mentioned smalltalk. Alan Kay was talking about how Erlang is really
an OOP language more so than other languages. In term of message passing and
each process is an object...

Erlang just let it crash and you can restart it with a supervisor process. I
think most of the time this model is much better since you won't be doing
numerical stuff with BEAM anyway, it's not for it and it's too slow.

------
andyfleming
How does Crystal lang compare to the two?

I know the syntax is more similar to Elixir, but the format seems closer to Go
in the sense that it compiles to a binary.

~~~
sudhirj
Swift would be a better comparison - both Crystal and Swift are general
purpose languages that compile via LLVM. Neither has any special story for
concurrency (yet). Go and Elixir/Erlang on the other hand, change your
approach to programming.

~~~
yxhuvud
What are you talking about? Crystal has a concurrency solution in their
Channel implementation. They are not yet running in parallel, but it most
definitely implement concurrency.

Or in other words, it is very inspired by the Go concurrency solution.

------
innocentoldguy
The article states that Elixir functions must be in a module, during its
comparison between Goroutines and one of the few methods of using concurrency
in Elixir (there are others beside _spawn_ ). This description isn't entirely
accurate. Named functions must be inside a module in Elixir, but anonymous
functions don't have that requirement.

~~~
brightball
I realized I wasn't clear on that after the fact. I should have said defined
functions. In my head I tend to think of defined functions and lambda
functions as different.

------
russellbeattie
The BEAM VM and lightweight processes seem amazing - I just wish they could be
tied to a language syntax that wasn't so radically different from
c/java/javascript and the like. Go code is almost immediately understandable
because of this, whereas Erlang is perplexing.

~~~
lightbyte
Have you looked at Elixir syntax? Elixir is functionally the exact same as
erlang, but with a more ruby-like syntax.

------
maxpert
I think it's comparing apples with oranges. They are two different species a
compiled vs VM based language, one is a functional styled vs other has duck-
tapping. Only thing I can see common is GC and a somewhat but very different
concurrency programming paradigms, with message passing. Erlang and BEAM is an
aged old giant with battle tested proven reliability, while golang is young
lad with the flash like abilities everyone has been longing for. While you get
awesome stuff like Hot-Reloading, Go lang gives you compiled code that can run
heavy loaded servers on my RaspberryPi (I made one and tried all Erlang,
NodeJS, and Golang believe me Golang smokes them all on memory footprint
[http://raspchat.com](http://raspchat.com) ). I can go on and on and on! But
picking one is totally dependent on your scenario.

~~~
pjmlp
> They are two different species a compiled vs VM based language

This is an implementation detail.

Anyone can write a VM for Go, or an AOT compiler to native code for Elixir.

~~~
timClicks
Pretty significant detail though, as no one has done either.. also "anyone" is
fairly strong, building decent compilers and interpreters is pretty difficult

~~~
pjmlp
Anyone with a decent CS degree should be able to produce working compilers and
interpreters, otherwise it wasn't a decent degree.

Of course, writing very good ones is a different matter.

~~~
coldtea
> _Anyone with a decent CS degree should be able to produce working compilers
> and interpreters, otherwise it wasn 't a decent degree._

Which would be useless for production without several years of maturity, a
tools ecosystem, and a community adopting them -- and of course continued
support.

So this is mostly theoretical.

~~~
pjmlp
So now compilers should only be written, if v1.0 is production ready?!

> So this is mostly theoretical.

No, it is setting the facts straight about the widespread ignorance of mixing
languages with implementations.

~~~
coldtea
> _So now compilers should only be written, if v1.0 is production ready?!_

No, but they are only relevant for the purposes of the discussion, that is,
when considering whether to adopt a language platform based on if it's AOT or
interpreted etc, when they are v1.0.

That somebody can always make an interpreter for an AOT language, for example,
is nothing people care about when checking whether to use a language for their
projects. It's what's there that matters.

~~~
pjmlp
Turning on cynic mode, I would say the only thing that matters is which
company backs a programming language and only languages offered on their OS
SDKs are relevant.

Anything else will just add entropy and development costs to projects, due to
2nd class tooling and lack of libraries on the target platform.

Then it doesn't matter how the code gets compiled at all.

~~~
coldtea
> _Turning on cynic mode, I would say the only thing that matters is which
> company backs a programming language and only languages offered on their OS
> SDKs are relevant._

That's true, but for application programming. For the server side there are
other considerations. WhatsApp can get away with using Erlang for example, and
still get the sweet billions.

------
spraak
[Deleted] Originally I'd had an off the cuff remark here of "apples to
oranges". I'd like retreat to say that the article is actually a good overview
and comparison

~~~
devmunchies
Nothing wrong with comparing apples and oranges. How else would you decide
which is best for any given use case?

