I think what most of the pro-erlang articles are actually extolling is the VM and not the language itself. The last 3 sections of the article are purely about VM features.
BEAM is an incredible piece of work, you can keep the syntax/string handling.
Yeah, that's not the tone I got from this at all. There are aspects of Erlang that can be hard to get used to, but it really isn't fair to criticize the language for not conforming to your previous experience.
Are you feeling a lack of breathless, relentlessly optimistic hype that whitewashes over all difficulties? Isn't that what the rest of the Internet is for?
I prefer to be told about the difficult aspects of my tools in advance, rather than having to discover them myself via hours of trial and error.
Bicycles have training wheels to get you going. Erlang doesn't. It might be hard and require effort.
I don't know how you learn new things, but it's generally taking me lots of effort: math, sports, music, etc. They're all hard when you first begin.
I remember I couldn't ever do anything good on a bass guitar (I started learning with a terrible sense of rhythm, not being able to clap on a 4/4 beat). I thought that music was just too hard, that the notation was too complex and obtuse for the sake of it, that improvising and jamming took some natural skill to get. It doesn't. All it takes is work, lots of it. It's hard because it's different and not something you pick up easily without prior experience. And even once I learned how to play bass (and have been for years now), I can't play drums for shit because it requires an entirely different way to think about music, notation and synchronism. You have to get in a different mindset when you switch instruments, or even just bands.
As for sports, mastery takes years. Of course someone in a good physical condition will pick up some of them with more ease than someone not used to many sports, but if you're a trained ice hockey player, the skillset you learn won't apply with the same ease for baseball or basketball when compared to roller hockey or field hockey. You have to go back to some basics. Re-learn how to position yourself, new strategies, discover muscles you hadn't trained before.
I see learning new programming languages as something somewhat related -- Languages can do their best to be friendly, but when the concepts behind them just vary wildly (see Prolog vs. C), you'll likely hit a wall. And it will not be the language's fault, but a question of you working hard enough to grasp it. Many languages have similar concepts and could be compared to switching from Bass Guitar to a cello, or from football to flag football. Python and Ruby have different syntaxes, but switching from one to the other is often a question of details. Even going back and forth with PHP is a similar thing. Going from Scheme to Common Lisp isn't as big of a leap as going from Prolog to C. I do believe Erlang (and many functional languages) fit this concept.
If you've never worked with them before, you'll be surprised by persistent data structures, the absence of O(1) arrays, message passing semantics, share-nothing ideas, lack of global data, an environment without main loops (or any kind of loops), different ways to handle exceptions, a specific way to package and write applications, lack of namespaces, new syntax, atoms, pattern matching, linked-lists as strings, bit syntax, etc. Of course the first contact will suck if many of these concepts are foreign -- you have to learn from scratch when you likely were very proficient in many other languages. You will be slow, your code might be slow, and everything will look unfriendly.
Obviously some languages are suffering from bad design, but knowing Erlang, I don't believe it's one of these. Hence my position on blaming lack of familiarity before syntax or any other reason. You have the right to disagree, but I would like to know your reasons for it if you do :)
The good kind of hard is a steep learning curve which is necessary due to the richness, expressiveness, and sometimes uniqueness of a language. Getting past the difficult learning curve is rewarded by being able to implement almost any solution naturally without having to shoehorn it too much to fit the idiosyncrasies of the language.
The bad kind of hard is like trying to learn to program in Malbolge or brainfuck. Yes it's going to be hard and requires a lot of effort to master. But getting past the learning curve yields little to no reward.
So difficulty of mastery is no indication of the quality of the language and, by itself, shouldn't be used as an argument in favor of a given programming language. I think your point is well made by letting the last two paragraphs stand on their own.
Sure, here is one example: error messages. I guess even the author of the article (you?) couldn't come up with a good justification for them. They are truly horrendous, cryptic and maddening to figure out.
There is just no excuse for a language that's twenty years old to not have reasonable error messages.
Strings are a whole story of their own, but simply saying "they're not that important" is just ludicrous if you simply take a look at all the efforts that every single programming language in existence take to make string manipulation fast and extensive.
The way the supervisor model is touted as a major improvement is also very disingenuous: you still need to create and maintain the chain of supervisors yourself, and nothing stops you from doing that in other languages. Erlang really has no advantages there.
The syntax and multiple separators also makes it very hard just to move code around (think: refactoring).
You shrug and say that the beginner just needs to try harder, I'm saying "they won't, they didn't and probably never will".
Erlang is an interesting academic curiosity but it's too alien and its creators are too blinded by their own brilliance to even acknowledge these very simple mistakes, so the world just moved on.
> Erlang is an interesting academic curiosity but it's too alien and its creators are too blinded by their own brilliance to even acknowledge these very simple mistakes, so the world just moved on.
You said some sensible things up until that point, but kind of go off the rails there.
Erlang is most definitely not an academic language, and Joe Armstrong is not a "blinded by his own brilliance" kind of guy at all.
Indeed, one of the real problems is that there is enough Erlang code in production (in critical roles) that they can't just go fiddle with the language, correcting some of the obvious uglies.
> The way the supervisor model is touted as a major improvement is also very disingenuous: you still need to create and maintain the chain of supervisors yourself, and nothing stops you from doing that in other languages. Erlang really has no advantages there.
This is total nonsense. You cannot write your own supervisors in other languages. The supervision tree works because Erlang processes can monitor each other. If you fail, I get sent a message. Error handling or orthogonal to the calling function stack. This is implemented underneath Erlang inside the VM and is baked into the entire run-time environment. The following languages to my professional knowledge do not support that construct: Fortran, Algol, Pascal, C, C++, VB, VBA, Java, Python, Perl, PHP, Ruby, Lisp and Haskell. All of these languages handles errors up the call stack.
If you want to write your own supervision trees then you need to implement your own run-time environment with your own custom language on top of it.
The only languages where I've seen supervision hierarchies an an explicit design principle have had explicit ports of Erlang's concurrency model, such as ConcurrentLua (http://concurrentlua.luaforge.net/).
Yet, the author of the article himself agrees with me:
"Yes, you need to create and maintain the chain of supervisors yourself."
> You cannot write your own supervisors in other languages.
Now, that is total nonsense. First of all, Turing complete is Turing complete, so your statement is wrong just on this basis.
Now if you want to argue that it's easier to maintain such a chain of supervisors in Erlang than, say, in Java, I'll just disagree. You spawn processes (lightweight processes) all the time in Java and monitoring their death is a few lines of code.
You just don't need the support of the JVM for that, and going further, I just don't see what JVM support adds for this particular functionality.
Hence my point that Erlang doesn't buy you much over traditional programming languages in that area.
Sorry - I call an Emacs skeleton function and use identical supervisors to every other supervisor. I have never written a line of supervisor code in 8 years of Erlang coding.
The Turing complete argument implies that representation is not important. Joe Armstrong has a great line for dealing with that red herring. He asks people to write an algorithm for doing long division with Roman Numerals. Guess what the representation of a number in Arabic numerals make alogorithms easy even though Roman Numerals are 'Turing complete'...
Having run an internet bank in J2EE with a budget of over $100m dollars and then built a clustered full stack in Erlang for under 1% of that I have the data to prove that your talking mince. Please bring your comparative costs to the table.
I agree that you need to maintain supervisor hierarchies yourself because you know your application better than any other method I know of at the moment.
As for writing your own supervisors being impossible, the better word might be 'impractical'. It's clearly possible to have supervisors on the JVM given Erlang has a version on there (called Erjang). In no way is it practical to have it in Java the language, because the language's semantics simply don't match supervisors as well and they wouldn't be that useful there.
You're making the mistake of taking all features one by one and saying "sure, language X can do that" without considering how they would interact together or how well they would fit the language as a whole. What happens when you have a bunch of processes linked together and you kill some of them while they're modifying shared data or holding locks? What happens to objects that are shared and that need to be converted when doing hot code loading in some processes while you kill processes holding versions that are too hold (because they're seen as oprhans)? How do you deal with preemptive multiprocessing and scheduling when everything is done at the same level in a single language? Can you keep the soft real-time constraints with the garbage collector you currently have (Erjang had to drop that constraint)?
It's [relatively] easy to just make a Frankenstein out of features because of Turing completeness. Making a sensible ensemble out of them is a challenge and Erlang does it in a way I haven't yet seen in other languages. If you've got other languages that do it as coherently and have been battle-tested for decades, I'll be glad to add them to the list. Until then, you might as well classify your arguments in the same category as the eternal 'sufficiently smart compiler' in terms of practicality.
* Error messages: The current format has two distinct advantages to the experienced programmer: They are Erlang terms and can thus be manipulated easily as such. And they are succinct. I definitely give you that they are not easy to read for the beginner, but for the more experienced programmer, they are actually easy to read. Your critique could be countered by writing a "beginners mode" which transformed the error into a more readable variant. Which isn't that hard to do but it takes resources which are better used elsewhere.
* Strings: Most functional languages, be it Haskell, Erlang, Ocaml, Lisp-variants and so on are usually better off with a representation of string-like objects which are symbolic. The reason is that symbolic manipulation is the strength of these languages - exactly as string-manipulation is the distinct advantage of perl. Furthermore the non-academic world in which Erlang was first used, telephony, has very little need for effective string handling, I might add. Not everything needs a string.
* Syntax: The syntax makes it harder to move code around, but not very hard. You will find that swapping the order of the last line with something else is a thing you do rarely. Even in pattern matches. At least I don't think it is much of a problem. Yet, I note that refactoring in other languages is not always exempt from similar problems. Changing type in java names in Java requires you to change the constructor call. Moving blocks of code in Python requires you to change their indentation. Hoisting a function out means you must create it. If it really pisses you off you can just write a style where the delimiter is at the beginning of each line and the . is on a line by itself. Then reordering is easy.
1. Error messages are sometimes cryptic and that is indeed a language flaw. Line numbers would be absolutely fantastic to have and it's a shame they're not there. I can agree on that. Other languages, however, do not uniformly do a better job at being clear when crashing. It's not a unique trait of Erlang to have unfriendly error messages.
2. Strings are important, but not the list type of strings all the time. Erlang, as I mention in the article, has 3 types of strings, and atoms. Jlouis' article had the best arguments for the strings not being that necessary (or rather, too depended upon in general circumstances). See PHP for an example of a language that depends on strings too much for everything.
This is also really dependent on the type of application you work with. Telecom software barely needed strings and rather needed ways to handle binary protocols. Some web apps will need them more than others. I might have painted them all with a brush too wide -- working with Erlang brings me to issues where strings are not needed that often and are frequently used as an opaque data type that you just pass on to some other piece of code somewhere else.
3. Yes, you need to create and maintain the chain of supervisors yourself. I am not aware of any AI system good enough to figure out what is alright to have crashing and what isn't, or how to react when problems arise, when to give up on restarting processes, etc.
I have my doubts about 'nothing stops you from having them in other languages'. I know Scheme with Thermite had them. What other languages have supervisors, monitors and links that can even work across nodes?
4. Refactoring is a valid point, and there are very interesting tools for that (see Wrangler: http://www.cs.kent.ac.uk/projects/wrangler/Home.html),
but there is more to refactoring than moving bits of code around: handling dependencies, breaking existing functionalities and regressions, etc. Syntax only makes one of all the problems of refactoring difficult. Referential transparency, success typings and all the other tools make it a lot easier. It's not all or nothing here.
5. It's fine that they might never will. Erlang isn't for everyone. I found it maps to my mental model of organizing things very well -- much better than any OO language out there. I can readily accept that for many people, the opposite is true.
6. Erlang is anything but academic at its roots. It was created in industrial setups by computer scientists and engineers with real problems to solve. It's been battle tested for decades and has received academic interest only afterwards and is now enjoying a presence both in the industry and in academia.
(I started learning with a terrible sense of rhythm,
not being able to clap on a 4/4 beat)
Ok so this fascinates me. I also have a terrible sense of rhythm which up to now I have allowed to discourage me from doing much musically. In your experience did you find that your sense of rhythm improved with practice?
Yes. Listening to music, trying to play over it. Get a metronome, play with it, even if it's only stretching exercises. You'll get a feel for it. Try playing the same song slow or fast, have someone with a sense of rhythm tell you how well you're doing (or play over a song that you can control the speed of -- midi software is great for that).
Then there's some music theory you can look for: Pop and rock music will usually have the base of the chord (unless it's a reverse chord) on the first time, with lots of emphasis on it. The third time will have some emphasis, but not as much. Reggae music will have it in a different way, with more focus on some upbeat times.
You have to practice, but you must practice smart. A very good exercise I had was playing in larger ensembles playing anything from classical, blues and some jazz music. I would sit next to a very good tuba player (with something like 50 years of experience) who I could listen to when music notation got problematic. With time, your brain starts to understand things and it helps, but it takes a lot of time and effort.
I'll add that even your ear can develop and recognize notes with more ease. In my case it's not the absolute hearing (finding out what note some random sound is), but rather relative hearing (telling the distance between two notes). I've been able to develop this over theoretical exercises where a teacher gives you a simple song and you have to write it down. Go from simple to complex, by removing and adding notes. Study scales, chords, how they sound and what they can evoke. With enough practice/training, your brain will absorb it and won't be entirely incompetent.
After 1 year of casual music training, I completely froze up on stage, losing my sense of rhythm and being unable to read the sheet I had in front of me. That's when I enrolled in the big band-like ensemble I menationed earlier -- suddenly I almost doubled my practice time, played genres I didn't know very well or listen to in my free time, and one year later, I was a good second bass player. After the third year, I could play on my own with very little problems. The fourth years was spent perfecting my technique and I spent the fifth year getting to learn how to improvise. It's been about 2 years since I stopped taking classes and playing seriously, but the sense of rhythm is still there.
It takes a lot of effort and perseverance. Things seem to move in staircase way: you start with a wall to get over and it seems like you'll never do it. At some point it clicks and you can enjoy yourself. You're now on a plateau of comfort, until you hit the next wall, and the one after that, and so on. Some are way harder than others, but they're all normal.
And for the love of God, please don't compare yourself to others (you won't be able to keep yourself from doing it). I used to do it all the time. Comparing myself with players who were half my age and twice better, regretting I didn't start earlier or thinking 'what is it worth? they're still better anyway'. It's not a contest, but you have to remember that mastery comes with time and rather compare how many hours of very serious practice you've done compared to others.
BEAM is an incredible piece of work, you can keep the syntax/string handling.