I had not even heard of Elixir till the Phoenix framework hit 1.0 about a month ago, and right now I'm very seriously considering Elixir/Phoenix for my next startup and have been slowly learning/hacking in it.
I come from C/C++ background, so the syntax was different as it is more Ruby-ish, but still very easy to grok. I've been looking at golang as my next language, but I think Elixir is even more simpler that it. Of all the functional languages that I've tried to get into in the past, this has the most approachable syntax, and I can see things like pattern matching helping a lot with code maintainability.
The performance, from whatever I've seen and the limited benchmarks that are out there, it compares extremely well with JVM, Node and Go. Erlang/OTP brings fault tolerance, Phoenix/Ecto etc. have been very productive, community is awesome and helpful. Erlang tooling, such as observer, is awesome and I don't think we have anything similar in golang, though I could be wrong. Dializer helps with type checking.
The one thing missing is lack of a enterprise sponsor, and also number of potential hires which can be risky for startups, but on the other hand people interested in working in elixir could be an interesting hiring filter ;)
To be honest with you, "for my next startup" strikes me as the absolute worst time to use a language/platform that is both new to you and new to the industry.
Delays kill startups, and that just begs for delays. You have to learn the language. All your new engineers have to learn it. You'll inevitably be (re)inventing the wheel because Elixir isn't in production at thousands of companies already.
Picking a shitty, slow language, as long as it's a popular one (JavaScript, Java, C#, PHP, Python), is going to have a much better cost/benefit profile.
> Picking a shitty, slow language, as long as it's a popular one (JavaScript, Java, C#, PHP, Python), is going to have a much better cost/benefit profile.
Although, keep in mind that a startup is going to be a roller coaster ride for years. You'll have days when you get tired of writing financial models for investors, or when an angry email from a customer ruins your mood, or you hit a road-block with a UI that just doesn't feel right. You'll want to take a break from all that by going back to just writing code for a day or two. At that point, you will want to get pleasure out coding. I'll be very unhappy if after those kind of days, I try to find solace in coding, and I see PHP, JavaScript or Java staring back at me.
Compared to the years it takes to turn a startup successful, the time needed to learn a new language well enough is negligible. I knew just basic Ruby when I switched to Ruby + Sinatra from Java for my new startup. Now, three years later, I can't be happier I made the switch.
Failing fast isn't easy if you're also learning a new language. You want to go from zero to product as soon as possible, and that means using a language you already know like the back of your hand, even if that language sucks.
For your first couple programming languages, it's intimidating to learn a new language. Once you're experienced, though, you discover that its easy and quick to pick up new languages.
Because my experience is, as I related above, even though I was learning elixir (for real, I had dabbled with it before) an building a team from scratch, we delivered a product extremely fast.... because we chose elixir.
It doesn't matter how well you know java, the language is going to slow down your development dramatically... at lest compared to Elixir (and maybe go.)
Not necessarily. I don't go from zero to product till I have verified that there's a need for the product. I try to fail fast before developing the product. By the time I'm developing the product, I'm fairly certain it's not going to fail immediately after launch. Oh, and once you've built a product that people are using and you're going after growth, you would rarely get a chance to switch languages or frameworks. So, then, you're stuck with the language that you don't even like anymore for many years.
I think you're also over-estimating the time required to learn a new language to be good enough for most startups. I understand that there are some areas where language mastery will be tremendous benefit. In that case, I agree that switching languages may not be such a good idea. But, that's a special case, IMHO.
Nope. And I have real world experience to contradict that.
Last year started a project with elixir, about 8 months before elixir hit 1.0. Despite starting with me and another engineer we both built a team, taught them elixir (the ones who didn't already know) and got a product to production within about 5 months[1].
Erlang is not new. It has been around for over 20 years. I don't think we needed to, but if there weren't an elixir library for what we needed, we had erlang libraries to fall back on. Our "new engineers" were often attracted to us BECAUSe we chose elixir. It took about a week for us to get new engineers productive with elixir (we hired good people, though).
You're over estimating the benefit of libraries and way underestimating the benefit of a really good language/platform.... and elixir/erlang is that.
It's a lot faster to create a given amount of functionality in Elixir, and then a lot faster to debug it and extend it.
And then, after making the choice to stick with an "established" language, companies are shackled to it forever, hiring people who already like that language and so they never leverage newer better ways of doing things.
[1] That was a year and several months ago that it went live. Five months may seem long, but this was a from-scratch ecommerce in a highly regulated industry involving a great deal of pulling customer records during the purchase process, with a parent company that didn't understand the concept of specs and kept changing it's mind on what it wanted. We were about %30 faster than a comparable other project at this company.
Yes, you're absolutely right. Which is why I'm extremely conflicted right now. I definitely like what I'm seeing with Elixir/Phoenix, but should I take the risk or not is a really tough question. It is performant and fault tolerant, so for a startup if that means it can reduce our operational, and support, cost that itself would be a huge win. Deployment seems straight forward, much much simpler than what I had to do with a Rails app that I was experimenting with. Go deployment would be easier, but Elixir seems at worst to be inline with Play/Java (running under Play and not tomcat). There is a huge set of libraries should I need to venture outside Elixir and into Erlang, and moreover I think (not 100% sure) that Erlang can easily call into other language libraries which might come in handy.
The way I'm looking at it is implementing small examples in a couple of other options, such as Nodejs/Loopback and Java/Play and then comparing them. So far Elixir/Phoenix seems straightforward and productive, but still evaluating.
However, even if Elixir/Phoenix is the best thing since sliced bread, hiring and training is indeed going to be an issue so I've been trying to figure out how to solve than conundrum.
Built a team from 2 people to 12 in 2014, starting 8 months before elixir hit 1.0 and didn't have trouble. We attracted a number of people simply because we were using elixir. We also got a number of people who were interested in functional programming.
Really, language should never be a barrier to hiring... a good engineer will want to learn a new language, and in my opinion, the really good engineers are already erlang programmers.
The biggest barrier to hiring, in my experience building a team for an elixir project, was medieval HR practices. ("oh you can't hire him, cause he wants a plane ticket reimbursed for relocating across the country. He's being greedy." Seriously.)
One counter point is the "Python Paradox"[1], though I don't know how well that conjecture was ever actually supported. However, isn't the Elixir/OTP ecosphere considered relatively practical and tested, rather than just esoteric or purist, even if it is new?
I can't speak to Elixir/OTP, as I've not -yet- used Elixir. However, every time I've gone to use something in the Erlang/OTP standard library [0] it has always been far less complicated and far more well designed than I feared it was going to be.
Maybe this is a reflection of my pessimism, but I feel that it is actually a reflection of the quality of the software. :)
[0] Yes, I know that Elixir is a BEAM language and -as such- has access to both Erlang and OTP, so this distinction is terribly fine. ;)
When PG says "smarter engineers", it isn't a given that there are more of them or that it matters that they're smart.
Many startups don't need top-tier engineers. They need productive, numerous engineers, especially at the beginning when hiring anyone is difficult (let alone someone good).
It really depends on the startup. For some form of chat application or distributed system he will find himself reinventing less compared to the competition. Would be a great way to beat the averages :)
I do not agree, I have worked for a year on a startup using Clojure(Script) and I hadn't touched Clojure before. Never looked back and did not encounter any major issues springing from the choice of language. To the contrary, I have really enjoyed not having to deal with the disadvatages of older languages. The issue could possibly be in hiring, if the supply of Elixir-developers would be scarce.
Kind of, since Elixir runs on the Erlang VM and it uses much of Erlang's libraries (e.g. OTP) I'd argue that you can look at Erlang's track record for Elixir's.
I worked for thredup.com when it was brand-new and we used Rails when it was still fairly new and we had a pretty good time all things considered. You just have to be a capable programmer. ;)
That list of languages was "popular" rather than "shitty and slow", although some of them certainly are shitty (and dynamic languages do tend to be kinda slow). I realize my phrasing was confusing.
I've been doing programming for a while now (mostly in Ruby of late, but prior to that, lots of stuff) and the more I play with Elixir, the more I want to work in it. I'm actually going to ElixirConf (which is next weekend in Austin).
They seem to have done a lot of things right, and addressed pretty much every single criticism I had of Ruby.
> I'm very seriously considering Elixir/Phoenix for my next startup
It will be a risk, but I say go for it. Others (who have probably NOT had any Elixir experience!!) will tell you your startup is already enough risk, but here's the thing- Elixir could end up being the key differentiator technology for you. Who else provides NO DOWNTIME code upgrades, and that incredible request responsiveness as well as reliability? Immutable data? Extreme concurrency? The "Actor model" that everyone is enamored with these days? The awesome community? Nobody, I think.
This is because Elixir is "just" a different syntax for Erlang/OTP which is used in very mission critical software in real world (it was originally created for telephone systems)
Yes it is. x is the variable. It changed from 1 to 2. Mutation is a synonym for change. Try it yourself in the interpreter! So data is immutable, but variables are mutable in Elixir.
Dude that's not a mutation that's a rebinding. You do not understand the difference, and it is an important one.
Again, Elixir does not create mutation where in Erlang there was none. There is no mutation.
They decided to allow rebinding so that you wouldn't end up with a whole bunch of stupid temporary variables, which is exactly what you have to do in Erlang.
That is a variable mutation. Mutation is a change in value. x was 1 then it was 2. If that is not mutation, I don't know what is.
You are probably trying to say that Elixir and Erlang have immutable data. But that's what that's called "immutable data". Precisely because the variables can be mutated or not separately from the data.
> a whole bunch of stupid temporary variables, which is exactly what you have to do in Erlang.
Well we should tell Joe that it's stupid. Maybe he'll change his mind.
If variables don't mutate, all it means is that the memory location that stores the value of that variable is guaranteed to never change. Thus, if you reassign that same-named variable, it actually points to a new memory location with the new value. That is what "rebinding" is vs. "mutating." The advantage of this is concurrency, etc. etc. The disadvantage is you have to have good GC since you'll be doing a lot more garbage collection. It may LOOK like it's changing a variable, but it's not- the variable merely points to a new memory location.
Other languages, like Ruby, do not work this way. If you reassign an instance variable, the memory that is storing that value actually does change.
Here, compare the same sequence of operations in Ruby and Elixir, first Ruby:
bash>> irb
>> a = {a: 5}
=> {:a=>5}
>> b = a
=> {:a=>5}
>> a[:a] = 10
=> 10
>> b
=> {:a=>10}
and now Elixir:
bash>> iex
Erlang/OTP 18 [erts-7.1] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.1.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> a = %{a: 5}
%{a: 5}
iex(2)> b = a
%{a: 5}
iex(3)> a = %{a | a: 10} # updates a mapping
%{a: 10}
iex(4)> b
%{a: 5}
Notice how b's value changed in Ruby, but not in Elixir. In both cases, the hash was updated.
I think we are talking about two different things when we say "variables". When I say "variable" I mean x, y, a, b etc. That is the variable. It has a value, you can see it in the shell (repl) or when printing it. Look at what happens to variable x:
iex(1)> x=1
1
iex(2)> x=2
2
It was 1 then 2. It changed. Mutation is a synonym for "change". I think it is a pretty simple concept. Did the framework create a new memory cell, put a 2 in there and now x behind the scene dereferences that. Did it update the old cell in place. Was it on the stack? That's not the point. The point is x now has a new value. x is a variable that means variable x mutated.
Compare to Erlang:
1> X=1.
1
2> X=2.
** exception error: no match of right hand side value 2
You can't mutate variable X. variable X is immutable. Again, I think that is pretty clear and simple.
What you showed in your example is how data is immutable in Elixir but not in Ruby.
> The advantage of this is concurrency, etc. etc.
Actually most data, except larger binaries, are copied between processes anyway. So concurrency advantage is mostly theoretical. In the future they could be switched to reference counting for other things. But that is a hidden implementation detail anyway.
This doesn't need to be a language feature, but this is possible on the JVM afaik (see Clojure).
Also, NO DOWNTIME in the context of services is kind of hard to qualify: I have no downtime for say, a web service, when doing a load-balancer deploy shuffle.
> incredible request responsiveness as well as reliability
"Request responsiveness" to some degree depends on language- a language is sometimes your upper-bound on performance.
Much more often, however, do I find that this is a function of application design. And yes, language design and application design heavily play into each other, but there are many, many languages that can achieve the same responsiveness/reliability concerns.
Haskell, many JVM-hosted languages are good choices.
> Immutable data
Almost every modern functional language. Many even do it (immutable data structures) better than Erlang/Elixir. Some even have interesting (state of the art) concurrency features that perform better in different situations - see Haskell STM (I wouldn't try and compare to Mnesia).
> Extreme concurrency
Haskell, Go, anything on the JVM, the CLR is catching up.
> Actor model
This is a bit of a subjective and semantic thing - many languages have green threads (though not all would necessarily fit the bill of "actor model" in out-of-the-box implementation, and not all are truly preemptive (most aren't)) - Haskell, Go are two good out-of-the-box implementations.
I know Haskell has an Erlang Actor analogue, not sure if Go does yet.
> The awesome community
I hesitate to use the word "niche language" - but most "niche languages" have great communities (albeit small ones) - possibly out of necessity.
I don't find that this scales often
(What would you call the "Java community?", where would you find it?, where are the pockets of "good?")
This is 100% subjective, but, I feel like Ruby has one of the best, largest communities. Some of that has bled into Elixir, for sure, to be fair.
---
All in all, Elixir is a great language, but I hesitate to recommend it without knowing more about GP's requirements and business.
(What if the GP needs to do very memory and CPU-intensive number crunching?)
You can nitpick like this about just about anything — "Erlang has immutable data? Yes, but so does Haskell etc.".
That's missing the point that Erlang/OTP (and therefore also Elixir) is attractive because it's already a complete package. It's the intersection of a lot of different, neat technologies that becomes magical.
Try to accomplish the same things in Haskell or Clojure or Go and you'll find that you simply don't have the same tools available to you, and often they cannot be built as well as in Erlang because the foundation wasn't designed for it. And there's always some piece missing.
For example, you can build an approximation of supervisor trees in Go, but since goroutines cannot be killed, you're at the mercy of the runtime. (I also wonder if goroutines scale as well as Erlang's.) Similarly, no one has actually built a functional, immutable, process-oriented call-by-name-and-signature RPC mechanism for Go, so you'll have to invent your own. And so forth.
As a specific example, I was recently investigating OCaml to see if someone had implemented something similar to OTP. I found a couple of promising, nascent projects, but their activity all ended around 2009. Apparently nobody is doing it, even though the language seems damn near perfect for it. Never mind distributed processes; LWT is pretty weak even as an approximation of Go's goroutines.
> [downtime] This doesn't need to be a language feature ...
Erlang's live code replacement changes how you mentally think about versioning, I think. Instead of designing every piece of your infrastructure to transparently transition to a new version — using load balancers, multiple processes accept()ing on the same port, and so forth — you get a first-class language construct. This also opens possibilities beyond code deploys, such as temporarily injecting tracing into a running program. Also not often mentioned is how powerful it is to be able to connect to a running process and run the REPL inside it. (Ruby comes close here, but it's never been something you get for free.)
> This doesn't need to be a language feature, but this is possible on the JVM afaik (see Clojure).
You don't need Clojure; Hot Code Replacement was added in Java 1.4 (yes, that's 2002) and has been supported by application containers as well as IDEs since then.
Never done it. But I don't think anyone claims you get hot code replacement for free. You have to plan and design your app to support it. That said, it's actually intended for downtime-less upgrades, whereas Java's HCR seems intended for debugging and development.
I had not even heard of Elixir till the Phoenix framework hit 1.0 about a month ago, and right now I'm very seriously considering Elixir/Phoenix for my next startup and have been slowly learning/hacking in it.
I come from C/C++ background, so the syntax was different as it is more Ruby-ish, but still very easy to grok. I've been looking at golang as my next language, but I think Elixir is even more simpler that it. Of all the functional languages that I've tried to get into in the past, this has the most approachable syntax, and I can see things like pattern matching helping a lot with code maintainability.
The performance, from whatever I've seen and the limited benchmarks that are out there, it compares extremely well with JVM, Node and Go. Erlang/OTP brings fault tolerance, Phoenix/Ecto etc. have been very productive, community is awesome and helpful. Erlang tooling, such as observer, is awesome and I don't think we have anything similar in golang, though I could be wrong. Dializer helps with type checking.
The one thing missing is lack of a enterprise sponsor, and also number of potential hires which can be risky for startups, but on the other hand people interested in working in elixir could be an interesting hiring filter ;)