Now majority of my experience coding is with object-oriented languages. We have classes and methods and polymorphism. We tie state and actions together which allows us to reason and work with things in a more natural way. A Dog barks, a cat annoys you, a MacBook Pro with an I7 burns us. Now what if we want that dog to bark and run? We do it in two separate steps and done in sequence in the same thread. Do it in two threads and now you need to start thinking about locking and I don't think any of us want to do that. We have made concurrency hard for ourselves due to how we reason in this paradigm. Perhaps not a big deal before but multi-core CPUs are everywhere now while CPU speed hasn't improved.
Now enter Erlang where instead of an object being a core concept you have a process (a light weight process not an OS process). So instead of thinking in terms of sequence of events that occur to objects you can think about the coordination of events between many processes. These processes take messages and perform actions based on those messages and possibly send out messages. The processes don't share state and you have to send any data in the message. Sending a message is a one way trip and if you are expecting a reply the one you sent to doesn't have to be the one who replies. You can also do other things while waiting for a reply or wait immediately.
Now this seems to work a little more like the real world. I think an easy example is just how we interact with each other with e-mail. I have an idea and I want to share it with you. You are pooping. I send you my idea and afterwards I decide to play Metal Slug instead of just waiting for a reply. You finish pooping to find a new message. Reading my message, containing my idea, you find it terrible and send a reply. I stop playing Metal Slug and check my mail which has your reply in it. I'm sad now and decide to post flame bait in forums I have no respect for. We are processes, our e-mail is our mailbox of messages, and everything else are the actions we decided to perform.
Erlang gives us an entirely different approach to structuring your application that allows us to code in a similar fashion to how we handle things in the real world. It seems to make it easier to think about concurrency by eliminating shared state and providing these process and messaging abilities for you as part of the core. At a lower level, Erlang is certainly a functional language so the state is disconnected from the actions generally, but an interesting thought is that Erlang at the higher level is actually object-oriented.
I got that from an interview with Joe Armstrong (author of Erlang) that I watched. The idea is that you still have the encapsulation inside your process, you still have the state and actions tied together (process holds onto the state and the messages it handles are the actions), and you have polymorphism in the fact that Erlang is dynamically typed and you don't know what process will actually handle your message in the end nor which one you will be sending it to in the beginning (since you can pass around process Ids or register names).
I hope that one day I can return to Erlang and try to accomplish something in it. I think there is a lot to gain from a language the presents you with a different perspective. In this post I haven't even touch topics like how Erlang provides extra reliability by allowing you to have watcher and worker processes, nor how it allows you to get almost linear performance gains from adding CPU cores. This is certainly a stand out in the crowd of technology I think.