Errors and processes in erlang
Previous posts about http://learnyousomeerlang.com: Dog FSM, Cat FSM.
Chapter Errors And Processes is closer to the beginning of the book and deals with core Erlang concepts: error propagation and error trapping.
First off, here is what I wrote to better understand the section that starts with words “the results of uncaught throws, errors and exits in neighboring processes”:
Here how the demo works:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1> c(simple_exit_demo).
./simple_exit_demo.erl:12: Warning: this expression will fail with a 'badarith' exception
{ok,simple_exit_demo}
2> simple_exit_demo:simple_exit_demo().
<0.38.0>
Caught a system message: {'EXIT',<0.39.0>,normal}
Caught a system message: {'EXIT',<0.40.0>,exiting_for_a_reason}
Caught a system message: {'EXIT',<0.41.0>,normal}
Caught a system message: {'EXIT',<0.42.0>,
{badarith,
[{simple_exit_demo,
'-start_processes/0-fun-3-',0}]}}
3>
=ERROR REPORT==== 30-Dec-2011::22:42:58 ===
Error in process <0.42.0> with exit value: {badarith,[{simple_exit_demo,'-start_processes/0-fun-3-',0}]}
Caught a system message: {'EXIT',<0.43.0>,
{raising_error,
[{simple_exit_demo,
'-start_processes/0-fun-4-',0}]}}
3>
=ERROR REPORT==== 30-Dec-2011::22:42:59 ===
Error in process <0.43.0> with exit value: {raising_error,[{simple_exit_demo,'-start_processes/0-fun-4-',0}]}
=ERROR REPORT==== 30-Dec-2011::22:43:00 ===
Error in process <0.44.0> with exit value: {{nocatch,throwing_error},[{simple_exit_demo,'-start_processes/0-fun-5-',0}]}
Caught a system message: {'EXIT',<0.44.0>,
{{nocatch,throwing_error},
[{simple_exit_demo,'-start_processes/0-fun-5-',
0}]}}
Show's over
3>
The second chunk of code I’ve written helps understand how the kill reason is different from other kill reasons:
The system process traps an exit and lives on, while exit(Pid, kill) kills it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1> c(kill).
{ok,kill}
2> kill:kill_demo().
I, <0.38.0>, live on
I, <0.38.0>, live on
I, <0.38.0>, live on
Sending exit(Pid, please_die) <0.38.0> to
<0.38.0> has caught a system message: {'EXIT',<0.31.0>,please_die}
I, <0.38.0>, live on
I, <0.38.0>, live on
I, <0.38.0>, live on
Sending exit(Pid, kill) <0.38.0> to
** exception exit: killed
3>
Cat FSM
As a continuation of my previous post about the chapter Rage Against The Finite-State Machines from Learn You Some Erlang for Great Good here is a gen_fsm implementation for the Cat’s FSM described in the chapter.
This is a primitive one-state FSM, but the difference is that synchronous calls are used.
The output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
27> c(cat_fsm).
{ok,cat_fsm}
28> cat_fsm:test().
Switching to 'dont_give_crap' state
<0.145.0>
Cat replied: ok
Switching to 'dont_give_crap' state
Cat replied: ok
Switching to 'dont_give_crap' state
Cat replied: ok
Cat receives an unknown global sync event: hello
Cat receives an unknown global event: how_are_you
terminating with reason normal at state dont_give_crap
29>
Dog FSM
Learn You Some Erlang for Great Good by MononcQc is a really good alternative to the two canonical Erlang Books Erlang Programming by Francesco Cesarini and Simon Thompson and Programming Erlang: Software for a Concurrent World by Joe Armstrong, especially when you need to jump into the language quickly. It gives you enough knowledge to build upon reading other people’s code, documentation, and coding.
Things taken for granted by Erlang programmers can be confusing to newcomers to concurrent and functional programming. Needless to say, jumping from, say, C# to Ruby is far less adventurous than from any of the two to Erlang. While reading the book I found out that readability of certain pages could be greatly improved by a few more code examples, and I spent time in the Erlang shell and my editor writing additional code to better undertand the concepts.
I did actually write an email to MononcQc with a few lines of code, and his reaction was positive, but the guy seems to be really busy at this moment to make any changes to his book, so in the meantime I am going to post code extracts here in my blog hoping that it will save a few brain cycles of future readers of the book.
The first example is for page Rage Against The Finite-State Machines . In this page the author first gives two examples of Finite-State Machines written in plain Erlang, an FSM for a cat, and an FSM for a dog. Then the author explains the API of gen_fsm, and right after that he goes on implementing a complex (at least for newbies) trading system with two FSM processes talking to each other and to their clients. 450 LOC together with the tests.
Hmm… There is something missing between the super simple naïve examples not using any APIs and then the complex stuff using gen_fsm. Namely, a rewrite of these two primitive FSMs with the use of gen_fsm. This way by the time the reader starts struggling through the complex part he would have already seen the gen_fsm API in practice. One thing less to learn at once.
Here goes the dog_fsm example:
Let’s run it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2> c(dog_fsm).
{ok,dog_fsm}
3> dog_fsm:test().
<0.41.0>
Dog says: BARK! BARK!
Dog says: BARK! BARK!
Dog wags its tail
Dog is sitting. Gooooood boy!
Dog is confused
Dog says: BARK! BARK!
Dog says: BARK! BARK!
Dog says: BARK! BARK!
Dog wags its tail
Dog says: BARK! BARK!
Dog says: BARK! BARK!
Dog wags its tail
Dog is sitting. Gooooood boy!
terminating with reason normal at state sit
4>
Notice the usage of gen_fsm:send_event_after to implement a transitions on a timeout, and the way the timers get cancelled if another event arrives. If the timer is not cancelled, the timeout event will be triggered at another state, not something we want to use it for.
Voila.
Happy erlanging!
CoffeeScript
So, it’s my turn to do something to get familiar with the new kid on the block – CoffeeScript .
I took a short 160 LOC JS file supporting my WiceGrid Rails plugin – https://gist.github.com/1067159 and rewrote it in CoffeeScript – https://gist.github.com/1067160 .
The JS generated out of the CoffeeScript code is here – https://gist.github.com/1067162
What I really liked is the syntax for javascript object literals in function calls:
1
2
3
4
5
6
7
jQuery.ajax
url: base_path_to_query_controller,
async: true,
data: request_path + '&query_name=' + encodeURIComponent(query_name),
dataType: 'script',
type: 'POST',
success: () -> $('#' + field_id).val('')
and this (look at “.join”):
1
2
3
jQuery.map grid_state, (pair) ->
encodeURIComponent(pair[0]) + '=' + encodeURIComponent(pair[1])
.join '&'
This not all all that CoffeeScript has in stock, but it seems than in order to use things like list comprehension you have to write code directly in CoffeeScript.
This new syntax could become a huge improvement for those writing big systems in javascript (think Node.js or RIAs like ExtJS or SproutCore), but with standard web applications, even modern and dynamic, the javascript that you write usually consists of short chunks and functions here and there, thanks to powerful frameworks like jQuery. And I just don’t see the point of adding one more layer for this kind of supporting code. I personally don’t mind writing it all in javascript, though I would love to use CoffeeScript merely for its beauty.
wicegrid versions 0.6.1 and 3.0.0.pre2
I have just fixed a nasty bug in WiceGrid. Use 0.6.1 for Rails 2, and 3.0.0.pre2 for Rails3.