It has been quite a while since the last blog post, almost a month, and its either that or the heatwave but I found that I had forgotten a lot of Erlang. So it was a little hard getting into it and it felt a bit weird picking it up again towards the end of the chapter. Which is unfortunate since the last section of this chapter focuses on Erlang's strength, concurrency. In particular the chapter shows a couple of methods to create lightweight Erlang processes that represent actors which receive and respond to messages. It then focuses on how one can monitor Erlang processes for failure and revive them if necessary following Erlang's "let it crash" philosophy. Onto the exercises, I only did the first [programming] one and then tried something else...
The exercise tied together a few things that had been demonstrated in the book. Using the example of a translator service (a process that takes a spanish word and returns the english translation if it knows it), we see the basic structure of an Erlang actor. The loop/0 function is the functions that the translator process will call when it starts, it enters a receive block which looks syntactically like the pattern matches we saw in day 2, however it defines the messages that this process will respond to. The conventions of the receive patters is to take the process id of the caller (From) and the word to be translated. This allows us to send a message back to the caller with the answer. Message sending is done with the ! operator. The last clause to the receive operator will catch any word the translator does not know and will actually quit the process. Which bring us to the monitor.
The monitor process (which i defined in the same file for convenience, using the name watch for its main loop function), basically sets itself up to trap exit signals from the translator, in which case it starts it back up. Note that it also responds to a message (new) to do the initial creation of the translator. This is all done in the spawn_link function. spawn/1 is a function that takes a reference to a function (using the syntax fun func_name/0) and starts a new process that will call that function. spawn_link/1 does the same but links the process being spawned to the one that called it (in this case the monitor). The linking is what allows this process to receive notifications such as the exit notification from other processes. This is all done inside a call to register, which lets us keep track of this process, by name, in Erlang's process registry. We can then refer to it using the atom translate in other parts of the program. When the monitor receives the exit message from the translator, it simply sends itself the new message to create a new one.
The other exercises focused on other aspects of monitoring and supervision, which i wasn't all that interested in. One thing it did encourage me to look up was the documentation for OTP, Erlang's Online Telecommunication Platform. This is a set of libraries, that i think would be fair to say form Erlang's standard library and contain a lot of useful functionality. For example there is a lot of functionality to make creating client-server programs and supervisor hierarchies like the one above simpler. However I wanted to experiment a bit more with taking advantage of Erlang's concurrency features for parallel processing so I thought I would try to write a parallel implementation of the lists:map function, that would spawn a process to process every element in the list.
I got pretty far along, but ended up turning to the internet for help (I was pretty close to the solution I ended up finding). This blog post is basically the implementation I ended up with; I had struggled to figured out the gather component and eventually just googled it. My code is here (almost identical to the blog post i linked to so I won't bother reproducing it on this page).
Overall I feel like i didn't get into Erlang's concurrency as deeply as I would have liked, that may be the long break since I last looked at it or just the reality of the book providing a small taste of each language, probably both. I think I would like to revisit Erlang some time to really play around with its concurrency features, maybe implement a basic map-reduce and try to get it to run across a network or a simple AI problem with a parallelizable solution. At the same time I would like to know how to get a few more basic things done e.g. file IO, more string manipulation and even just running erlang programs outside of the repl (which i just never bothered to figure out how to do). Not sure when that will be though, in coming back to Seven Languages in Seven Weeks I find a desire to work my way through the book a little faster and maybe pick one language to go deeper into for a while and use for side projects.