An Erlang process is arguably more the object that Alan Kay had in mind when he first conceptualized Object Orientation than what we today call objects. Message passing as a paradigm is in my somewhat-experienced opinion really neutered when there's still only one thread of control.
The following won't produce a perfect Erlang design, but it's a start:
1. Create your traditional OO design.
2. Anything that isn't obviously a collection or glorified struct, instantiate as a process and write them as gen_servers (or relevant other OTP process instead).
3. Anything that is obviously a collection, use one of the language's collections instead; if you really need typing on those, layer it on top with a tuple. Anything that is obviously a glorified struct is a record with a central module representing the "methods" as functions on the record.
Like I said, this won't out-of-the-box produce a great design, but the mapping will actually get someone used to OO but not used to Erlang at least started understanding how it works in practice. You've got several million-ish processes to play with, and in most programs you will not need to exceed that; that is the idea behind the comments I made about "collections" and "structs", because while it's easy to have millions or yet more of bits of data you can write a lot of programs with even "a few hundred" serves floating around.
You get polymorpismish by passing PIDs around as objects and implementing interfaces, only this time it's literal server interfaces instead of syntactic sugar. You get encapsulation by the fact that processes simply can not peek in on each other; this is actually even more rigid than most OO languages, no friends, no public, no sharing. Inheritance is pretty manual. So, two of the three usual OO characteristics are there.
I find my designs end up in a way that I'm not comfortable calling strictly OO, but if you used OO terminology and an OO diagramming language to show, everybody would understand what you meant. Given the way inheritance has been getting downplayed in the OO community anyhow, well, I wouldn't call Erlang an OO language by any means but I use a lot more of the "OO mental machinery" when I'm programming in Erlang than I do when I'm programming in Haskell. It's not as foreign as you might think at first, there's a lot of crossover there. Arguably it's a better OO language than the languages that wrote inheritance into their syntax and runtime too hard, and arguably it's not, but it's an interesting argument.
Great post, but if you put things into practice like "write them as gen_servers", the resulting code will be way more verbose than something like Ruby.
I think some way of creating 'object processes' with methods and state would greatly benefit Erlang. I mean, if it's such a common pattern, why not make it simpler, easier and possible with less boilerplate.
I think when selling Erlang it is best not to oversell the concision. Writing something in Erlang can be concise, but where you get the benefit is when you write something in Erlang that really benefits from the libraries and message passing. A gen_server may look somewhat verbose, but remember you're getting the supervisor tree, code upgrading, and a variety of other things with that. If you have to implement that in C it's going to really cost you.
But if you're just sitting there writing "algorithmic" code, well, maybe it's a 2x or 3x advantage over C because you're not managing memory and the pattern matching can be nice, but it's no Ruby or Python. You really only get the 5x-10x advantage over C(++) if you're playing to Erlang's strengths, it does not have the generic ability to cut down code like well-written Ruby, Python, Haskell, or other languages that pride themselves on being concise. In fact Erlang's metaprogramming facilities are frustratingly thin if you're used to having some around.
If you're interested, consider Lisp-Flavored Erlang, but I have no direct experience with that. (That's because my primary Erlang is actually using it at work, and while it's perfectly OK that I'm using it, I see it as advantageous not to make it necessary for my successors to have to learn both Erlang and Lisp to work on my stuff. If I ever have a home project with Erlang I suspect I'd lay one of the syntax replacements like LFE on top of it, if only to play with it.)
> If you have to implement that in C it's going to really cost you.
I'm not sure C is a good language to compare Erlang with. I think the competition these days goes from Ruby and Python to Scala and Java. I mean, if you're not beating C in terms of verbosity (which Erlang does handily, comparing apples to apples), and you're much slower, what's the point...
The following won't produce a perfect Erlang design, but it's a start:
1. Create your traditional OO design.
2. Anything that isn't obviously a collection or glorified struct, instantiate as a process and write them as gen_servers (or relevant other OTP process instead).
3. Anything that is obviously a collection, use one of the language's collections instead; if you really need typing on those, layer it on top with a tuple. Anything that is obviously a glorified struct is a record with a central module representing the "methods" as functions on the record.
Like I said, this won't out-of-the-box produce a great design, but the mapping will actually get someone used to OO but not used to Erlang at least started understanding how it works in practice. You've got several million-ish processes to play with, and in most programs you will not need to exceed that; that is the idea behind the comments I made about "collections" and "structs", because while it's easy to have millions or yet more of bits of data you can write a lot of programs with even "a few hundred" serves floating around.
You get polymorpismish by passing PIDs around as objects and implementing interfaces, only this time it's literal server interfaces instead of syntactic sugar. You get encapsulation by the fact that processes simply can not peek in on each other; this is actually even more rigid than most OO languages, no friends, no public, no sharing. Inheritance is pretty manual. So, two of the three usual OO characteristics are there.
I find my designs end up in a way that I'm not comfortable calling strictly OO, but if you used OO terminology and an OO diagramming language to show, everybody would understand what you meant. Given the way inheritance has been getting downplayed in the OO community anyhow, well, I wouldn't call Erlang an OO language by any means but I use a lot more of the "OO mental machinery" when I'm programming in Erlang than I do when I'm programming in Haskell. It's not as foreign as you might think at first, there's a lot of crossover there. Arguably it's a better OO language than the languages that wrote inheritance into their syntax and runtime too hard, and arguably it's not, but it's an interesting argument.