This is still very alpha, but I'm submitting this because I really hope this succeeds. Erlang is really powerful and provides more modern paradigms for concurrent programming that just are not easily implemented in other VMs. However, Erlang's prolog inspired syntax is a big turnoff to many programmers. This could be a breakthrough.
Voting you back up to 1, after you had predictably been downvoted...
You're not alone here.
I gave erlang more than one shot and really, really wanted to like it. It promises to simplify and robustify some of the most thorny distributed programming problems that I'm dealing with nearly every day, in ruby and python.
But, just like you, I couldn't get over the syntax. It's ugly. It's error-prone. It's ugly.
And that's a dealbreaker. The most powerful VM doesn't help when you have to work uphill against arcane syntax all day long. Nobody wants to do that. That's why ruby is so popular, despite the trainwreck that is MRI.
Don't cheat yourself...Erlang itself is not that hard once you understand the core principles. I will say that OTP can be overwhelming, but with tools like rebar taking care of the bulk of it for you now, it's much more accessible to beginners. The learnyousomeerlang.com guide as well as the "Erlang and OTP in Action" book are really great resources for starting out. Stick with it, you'll be glad you did.
While the Erlang syntax is certainly a bit unusual I suspect that the greater adoption of Erlang is hampered more by other things.
For instance, there is tool support. As with any language that isn't very widely used there aren't that many tools for the language. It makes it more difficult to get up and going in a short manner. This is especially true if you're on Windows since many Erlang projects don't work on Windows (even though the VM itself has Windows support).
Beyond that, Erlang uses a model of programming and concurrency that isn't commonly used elsewhere. While you can get many of the features of Erlang in other systems, you are generally making an intentional effort to do so. Things like messaging passing, processes and hot code swapping are at the core of the language and getting used to things like this can be a bit overwhelming.
On top of that many of the Erlang projects I've worked with have extremely sparse documentation. There are many cool projects out there like Mochiweb, Nitrogen, etc. but getting up and going with them can at times be an exercise in frustration.
I think these things combine to make a barrier to entry that is much larger than people's syntax preferences.
I think Efene/Ifene is better for this task (just different syntax for Erlang, without changing Erlang semantics). No performance overhead.
Reia has completely new semantics and run in interpreted mode over BEAM (Erlang VM).
I personally think, that if programmer can't adapt to new syntax, it will be much harder to her/him to adapt to new semantics.
Erlang's syntax is ugly comparing to modern languages like Ruby. The simple things are hard to do in Erlang and simple in Ruby, but complex thing are easy in Erlang and impossible in Ruby.
Erlang is pragmatic choice for today. Maybe in 5-10 years Erjang,Scala,Go,Rust or some other new language will be a better choice, but until then use Erlang/OTP.
Reia isn't "interpreted" in any manner different from the Erlang language itself. It's somewhat similar to CoffeeScript in that it uses parse transforms to produce Erlang parse trees which are then compiled by the Erlang compiler just like any other Erlang source code. However, it's a bit more like JRuby in that it ships a runtime, core types, and a standard library.
It's slower than Erlang, not because it's executed in a different manner than Erlang, but because it supplies a separate late binding mechanism for dispatching methods to their receivers.
Yeah, I don't mind it either. Syntax is not a big deal to me, I care more about the unique capabilities of a language are. But I have heard other developers say they hate it.
I was mostly using Ruby when I switched to Erlang full time 5 years ago and I really struggled with the syntax.
I have got to start writing Ruby again now (to use the OLE libraries which I ain't going to reimplement). Ruby looks like line noise now.
The key thing about switching to Erlang is that it is not a programming language choice. Erlang/OTP is an Application System that runs on one or more computers. We stick with Operating Systems (including super-ugly ones like the Unices) because of the benefits of knowing that your unwritten software can write to disk, speak to a network, use a GUI etc. Once you have started writing to an Application System where your unwritten software knows how to fail over to a new machine, you ain't going back.
The syntax could be nicer? Who cares? Love the one your with is my experience - oh and I really do heart the mighty Erlang.
I too have been following Reia since he started it up and... well, I'm consistently disappointed. I'm putting this out there publicly because it's come up with co-workers. In the end, he's waffled with so many language design decisions that, in my opinion at least, it's turned into a language that on one end doesn't have the true syntactical flexibility of Ruby, and on the other side has buried a lot of what is most useful in Erlang. For alternatives I would suggest Lisp Flavored Erlang http://forum.trapexit.org/viewtopic.php?p=40268 or Efene / Ifene http://www.marianoguerra.com.ar/efene/ - both of which do much better at being Erlang-(but-with-better-syntax).
Edit: This is referring to its current state only- I reserve the right to change my mind in the future (:
Hi, Reia's my thing. My view on waffling on language design decisions:
If you're working on a language project, fuck it up, and don't do a rewrite, you get PHP.
That said, your other criticisms are valid: much of Erlang's functionality doesn't have first class Reia support (but is still directly callable through the presently undocumented Erlang interfacing syntax)
Many of Ruby's great features aren't available in Reia yet either. I'm shooting for a subset of Ruby's metaprogramming features which aren't incompatible with Erlang-style code loading.
The word waffling was too negative, and you're right. I apologize and I'll definitely keep watching. Erlang and Ruby are my two favorite languages as well, so if you do pull it off at some point, you'll have my support (:
I feel that we spend too much time worrying about the syntax of programming languages. I don't find switching between typing in erlang/lisp/java/ruby code any more difficult. All I do is switch IDEs (or plugins) and I'm at about the same level of productivity typing wise.
Semantics are much more interesting to talk about, but it seems we never do talk about them. We rarely have holy-wars over the semantic differences between (for example) c and lisp, or lisp and Erlang.
There are certain problems that are easier to solve when expressed as many concurrent processes. In this same way, there are certain problems that are easier to solve when expressed as self modifying code or a tower of objects, or low level bit bashing.
At a certain level, different syntaxes do absolutely nothing for me. No matter what I'm doing with code, I am manipulating a syntax tree. I'm never thinking about the syntax on the page as the 'code,' what is on the page is just a representation of the 'code' that is in my head and being run by the computer. And the semantics of that 'code' is what influences how I use the language.
Syntax on the page is almost a deception. Kind of an illusion that influences you into thinking about the code in a certain abstract way (a spatial 'on the page' arrangement of different parts), when really, the code was already abstract to begin with (runtime execution 'arrangement' of the different parts).
This is a cool and fun project, but a lot of people in the thread are pretty confused about erlang syntax so I wanted to post this.
erlang's syntax is not some arcane afterthought, it may look strange or even "ugly" to people not familiar with it, but it has been very well thought out and purposeful, every time there is a choice between a beautiful construct that can add confusion, or a less elegant solution that is crystal clear, erlang chooses less elegant every time.
I have been doing javascript since I started programming and still get confused by its object model + prototypal inheritance, the same is true for pretty much every language, python, ruby, c++ etc going back to erlang is a refreshing break.
Erlang is based originally on Prolog, a logic programming
language that was briefly hot in the 80's. Surely you've
seen other languages based on Prolog, right? No? Why not?
Because Prolog sucks ass for building entire
applications. But that hasn't deterred Erlang from
stealing it's dynamite syntax.
Until our species gets rather better at quantifying the effect of communication mediums' on cognition I take issue with Mr. Katz's assertion. The semantic meaning of Erlang and prolog code is such that ideas can be expressed rapidly, in my experience. Besides, taste in syntax is like taste in tea: you might prefer a light cup of Earl Grey, I might like mine over-brewed and bitter. Prolog's syntax--and by extension Erlang's--is an acquired taste, perhaps; I like them both.
You of course have a point in that "you can't argue with taste".
However programming languages live and die by the size of their community. Erlang has, by choice of an over-brewed and bitter syntax, drawn itself into a niche much smaller than it deserves. The only chance to escape would be to adapt a more popular taste.
Otherwise it will eventually be obsoleted by a language "as powerful as erlang, but minus the arcane syntax".
Erlang's semantics are so very different from most other languages that having an arcane Prolog-derived syntax is just insult to injury.
In addition to all the conceptual, semantic leaps that Erlang asks you to make, you also have to learn a syntax which is very different from the Algol/C-based languages most people are used to.
I buy the argument that maybe, if you get used to it, Erlang's syntax can be beautiful. But it's still very much a barrier to people who have never used the Prolog language "family" (which as noted earlier includes... Prolog and Erlang).
In my personal experience having used Erlang for some 3 years now, I still find its syntax ugly and obtrusive.
I found I adapted to Erlang's syntax in under a week. I'm far from proficient in Erlang, but it's not an issue of syntax, rather experience.
Erlang syntax is a bit different, and there are even (IMHO) internal inconsistencies, but I didn't find it any more of a roadblock than e.g. python's indentation conventions. Each person is different I guess.
What would make this more attractive to me is a mechanism for local mutable state. Some algorithms are just easier to express if you're allowed to change the values of some local variables. Erlang has no shared mutable state, but as Haskell's State monad shows, it's perfectly possible (and often useful) to keep mutable state boxed off safely.
Since this can be transformed to tail-recursion, you should be able to implement it on the Erlang VM without too much trouble. Getting a convenient syntax and doing the transformation would be the hardest part.
I used to agree with you but now I don't. I was particularly moved by some of what Joe Armstrong, Erlang's creator, had to say in the book "Coders at Work". He noted that after attending several functional language conferences, immutable state was much more a common quality of truly functional languages than other things people typically associate like static typing or lazy evaluation.
Reia is an immutable state language, and I think it's primarily a functional language, but one with a lot of features that make it less painful to use than languages like Erlang or Haskell.
In a language like Erlang, immutable state allows you the potential to send zero copy messages between actors. This can be hugely beneficial for exchanging state in a shared nothing system like Erlang.
That said, the Erlang VM doesn't work this way. There have been experiments like the shared and hybrid heaps to enable this, but they've largely been failures, not because they're conceptually flawed, but because the garbage collection in Erlang is relatively simplistic. Erlang processes are independently garbage collected so they never needed to deal with concurrent garbage collection or a shared heap before.
Erjang (Erlang on the JVM) uses Java's shared heap and lets you use the wealth of pluggable garbage collectors available on the Java platform.
In a quick test of the "chameneos-redux" benchmark on Erlang BEAM vs. Erjang, a benchmark which generates lots of messages and can benefit immensely from sharing state, Erjang was about twice as fast as Erlang.
I'm definitely not talking about mutable state that's shared between processes. I don't want global variables, or any such thing. I just want to be able to write little blocks of code where I can change local variables. To illustrate what I'm getting at, here's some code in JavaScript which will calculate the nth Fibonacci number:
function fib(n) {
var a = 0, b = 1;
for (var i = 0; i < n; i++) {
var temp = a + b;
a = b; b = temp;
}
return 'fib(' + n + ') = ' + a;
}
It uses a for loop. Of course, you could do the same thing with a tail recursive function, or probably some higher-order-function trickery, but a for loop is a very direct way of putting it.
But how do we implement this on the Erlang VM? It doesn't support any of this dangerous mucking around with the values of variables! As you rightly point out, there are good reasons for this. What we can do is convert this to, essentially, continuation-passing form. This looks awkward is JS, but it gives the same answer:
function fib_cps(n) {
function forloop(a, b, i, cont) {
if (i < n) {
return forloop(b, a + b, i + 1, cont);
} else {
return cont(a);
}
}
return forloop(0, 1, 0, function(result) {
return 'fib(' + n + ') = ' + result;
});
}
The for loop was converted to a tail-recursive function which takes the values of all the mutable local variables and tail-calls some function with (some subset of) these mutable local variables. Since Erlang has proper tail-call support, this should be no problem. And it doesn't require any modification to how heaps are handled, or Erlang's garbage collection scheme, or anything. It "just" takes some compiler work.
That's what I had in mind. Does it sound more reasonable?
Yes, I've wanted to implement for loops and while loops that can alter the local binding for awhile (that compile to separate functions in the same way Erlang compiles list comprehensions to separate functions)
It is not that you COULD do it with recursive functions - recursive functions are the native idiom of functional programming - it is how you DO do it.
Erlang is a functional programming language and as such it does a lot of list processing. Where imperative or OO programmers use for loops functional programmers work on lists, a lot. Yes, it will seem strange at first, but that the nature of the beast.
It is worth understanding why it looks odd:
* it uses pattern matching (what's that?)
* the function fib/1 has 3 clauses and fib1/3 has 2 (WTF?)
* it contains list operations (eh?)
Unless you understand those three things you can't write Erlang. Syntatic sugar to hide them from you is not your friend here.
The function fib/1 has three clauses - if N is 0 or 1 it returns the starting elements of the fibonaci sequence. If it is an integer greater than that it calculates the sequence using the function fib1/3
The function fib1/3 has 2 clauses. The first is the terminal clause - when I have counted up from 2 to N return the sequence.
The second clause is the recursive clause, calculate the current fibonaci number, stick it on the end of the list of all the fibonaci numbers calculated so far, and call myself for the next value up.
Acc is a list
[{I,V1+V2} | Acc] is a new list
with the new value {I,V1+V2} at the head of it.
In the function clauses of fib/3 I pattern match out the last 2 values of the fibonaci sequence as they are what I need.
Going into the clause the accumulator list looks like this:
[{11,89}, {10,55}, {9,34}....]
I need the last two values to calculate the current one, so I do a pattern match:
[{_K1,V1},{_K2,V2} | T] = Acc
(There is an Erlang convention that 'variables' whose names start with '_' are scratch - you are not going to use them, this is why my key values are called '_K1' and '_K2').
Pattern matching says 'if this pattern matches' stick the appropriate values from the righthand side into the as-yet unmatched 'variables' of the left hand side. Because V1 and V2 have not yet been given a value they aquire the values of 89 and 55 in this instance.
The terminal clause (ie the first clause of fib1/3) also uses pattern matching:
fib1(N,N,Acc) ->
This clause is only executed when the first 2 parameters are the same.
The mistake you are making is thinking that Erlang doesn't have a for loop like Javascript or Ruby, when the real difference is that Erlang doesn't have an '=' operator like Javascript or Ruby. In Erlang '=' is a pattern matching operator. You can't set the value of an Erlang 'variable' to anything, but that doesn't matter because Erlang doesn't have variables.
Pattern matching as a core language feature has as a consequence an absence of variables, which has as a consequence the absence of for loops.
Throwing out the baby of pattern matching for the bathwater of for loops is to miss the point big style.
Learn to love lists, learn to write recursive functions, learn to pattern match - you can't do functional programming without them.
Believe me, I know all about pattern matching, recursive functions, and all that fine functional programming stuff. If I wanted to write a recursive Fibonacci function, using an accumulator is the first thing that would come to mind. But that's not the point. I'm not asking anybody to throw out pattern matching, or recursion, or any of that. I'd just like to be able to write locally non-functional code.
Look at your native Erlang implementation of fib again. Would you say that it's easier to understand than the version I posted which uses a for loop? It uses an accumulator and an auxiliary tail-recursive function; I know you get used to writing like that after a while, but I'd like another option.
Haskell demonstrates conclusively that this is possible. We don't have to choose between pattern matching or mutable variables; we can have both, cleanly, as long as there's a way of keeping the mutable variables isolated in a safe box where they can't affect the rest of the program. In Haskell, this is the State or ST monad. In my proposal, mutable variables would be function-local, and such code is transformed to use tail-recursion. (This is what Haskell's State and ST monads do behind the scenes. The same could be done by a compiler with Erlang as the back-end.)
But why would you want to do that? This is the sort of madness that led C++ into hell. Sometimes '=' is this sort of operator, sometimes it is that. The old Perl maxim of make it possible to write the same thing in sixteen different ways is another fresh hell.
85% of the cost of softare is in code maintenance. Suddenly spawning multiple idioms for the same thing is madness. This proposal would directly increase the cost of running my software house - just not ever a good idea.
It has global state. In erlang processes are long lived and you bring functions to them to do stuff. Suddenly you will do something and a piece of state that you weren't expecting will be in your process dictionary...
Some erlang processes run for literally years - and exist over multiple releases of the software. Reasoning about how something did or did not get into the process dictionary is for the birds.
I think the consensus in 2009 was you should see how far you can get with ETS (and this will motivate me to read the R14 release notes), PD's are kind of like lisp reader macro's, very sharp and very slippery. There are many threads in the google group if you want more argumentage.
With all due respect metabrew, if you do that you are a nutter.
Non-mutability is not some crazy quick left there as an afterthought - it is at the core of Erlang - it is how you build reliable systems in the presence of errors.
Here's a question. Does there exist a decent stand alone representation (BNF or otherwise) of the Ruby grammar? I see all this stuff that says Ruby-style, and it looks almost like straight up Ruby. Moreover, I Google around for a Ruby grammar and can't find much of anything substantial, but I haven't looked in awhile. I've tried cruising the Ruby YACC file, but that's kind of a disaster. Is there good one that exists as a reference for 3rd party Ruby implementations?
You might take a look at http://mirah.org, which is Charles Nutter's (creator of JRuby) forging of Ruby-like syntax with static typing that compiles to Java bytecode.