Learn You Some Erlang for Great Good!

Learn You Some Erlang for Great Good!
A Beginner's Guide
by 
Fred Hebert
January 2013, 624 pp.
ISBN-13: 
978-1-59327-435-1

"I hope that many of you will enjoy reading Fred’s book as much as I did and that you find learning Erlang to be an agreeable and thought-provoking process."
Joe Armstrong, designer of Erlang

"I like this book. It's a complete description of the Erlang language together with many practical examples. Most importantly, it explains OTP, a set of design patterns and behaviors which allow you to build fault tolerant and robust systems."
Robert Virding, co-inventor of the Erlang language

Erlang is the language of choice for programmers who want to write robust, concurrent applications, but its strange syntax and functional design can intimidate the uninitiated. Luckily, there’s a new weapon in the battle against Erlang-phobia: Learn You Some Erlang for Great Good!

Erlang maestro Fred Hébert starts slow and eases you into the basics: You’ll learn about Erlang’s unorthodox syntax, its data structures, its type system (or lack thereof!), and basic functional programming techniques. Once you’ve wrapped your head around the simple stuff, you’ll tackle the real meat-and-potatoes of the language: concurrency, distributed computing, hot code loading, and all the other dark magic that makes Erlang such a hot topic among today’s savvy developers.

As you dive into Erlang’s functional fantasy world, you’ll learn about:

  • Testing your applications with EUnit and Common Test
  • Building and releasing your applications with the OTP framework
  • Passing messages, raising errors, and starting/stopping processes over many nodes
  • Storing and retrieving data using Mnesia and ETS
  • Network programming with TCP, UDP, and the inet module
  • The simple joys and potential pitfalls of writing distributed, concurrent applications

Packed with lighthearted illustrations and just the right mix of offbeat and practical example programs, Learn You Some Erlang for Great Good! is the perfect entry point into the sometimes-crazy, always-thrilling world of Erlang.

Bonus: ebook is in color!

Author Bio 

Fred Hébert is a self-taught programmer who taught Erlang. He spent time working on a real-time bidding platform and was named Erlang User of the Year 2012, and has since joined the routing team at Heroku, building large scale production systems with Erlang. His online tutorial, Learn You Some Erlang for Great Good!, is widely regarded as the best way to learn Erlang.

Table of contents 

Foreword by Joe Armstrong
Introduction

Chapter 1: Starting Out
Chapter 2: Modules
Chapter 3: Syntax in Functions
Chapter 4: Types (or Lack Therof)
Chapter 5: Hello Recursion!
Chapter 6: Higher-Order Functions
Chapter 7: Errors and Exceptions
Chapter 8: Functionally Solving Problems
Chapter 9: A Short Visit to Common Data Structures
Chapter 10: The Hitchhiker's Guide to Concurrency
Chapter 11: More on Multiprocessing
Chapter 12: Errors and Processes
Chapter 13: Designing a Concurrent Application
Chapter 14: An Introduction to OTP
Chapter 15: Rage Against the Finite-State Machines
Chapter 16: Event Handlers
Chapter 17: Who Supervises the Supervisors?
Chapter 18: Building an Application
Chapter 19: Building Applications the OTP Way
Chapter 20: The Count of Applications
Chapter 21: Release Is the Word
Chapter 22: Leveling Up in the Process Quest
Chapter 23: Buckets of Sockets
Chapter 24: EUnited Nations Council
Chapter 25: Bears, ETS, Beets: In-Memory NoSQL for Free!
Chapter 26: Distribunomicon
Chapter 27: Distributed OTP Applications
Chapter 28: Common Test for Uncommon Tests
Chapter 29: Mnesia and the Art of Remembering
Chapter 30: Type Specifications and Dialyzer

Afterword
Appendix: On Erlang's Syntax
Index

View the Index (PDF)
View the detailed Table of Contents (PDF)

Reviews 

"An excellent introduction to Erlang. . . . If you want to know it all, Learn You Some Erlang for Great Good! is a great book to buy."
Jesper Louis Andersen, Erlang Solutions Ltd. (Read More)

"Learn You Some Erlang for Great Good! is an inspiration. An indispensable guide to a very important programming language."
Michael Fogus, author of The Joy of Clojure and Functional Javascript (Read More)

"I recommend LYSE to all those who want to learn Erlang and OTP, especially to those who want to experiment and self-learn the language and system."
Dr. Kenji Rikitake, Basho Technologies (Read More)

"A great place to start exploring the topic."
Mark Gibbs, Network World (Read More)

"A fun to read book on programming? Takes you through virtually everything you need to know about not just Erlang, but the underlying context/philosophy associated with Erlang, viz., developing reliable and fault-tolerant applications and systems."
Mahesh Paolini-Subramanya, Vice President of R&D, Ubiquiti Networks (Read More)

"A must-read book every developer out there should add to his Erlang shelf."
Paolo D’Incau (Read More)

"The book has great and funny illustrations; technical yet with a nod to the whimsical, without being inscrutable and self-indulgent. If you’re interested in Erlang, this is the Erlang book to read."
Bryce Kerley (Read More)

"Fred's style is breezy without being flaky or muddle-headed. His examples are often comical, sometimes thought-provoking and yet always salient and to the point. His jokes keep the tone light and allow him to sneak difficult concepts that your brain would traditionally reject as 'too hard' past your defenses so that you often learn in spite of what you think you can do."
Michael Richter (Read More)

"This is how a programming book should be. The contents of the book were detailed, easy to follow, engaging, and surprisingly humorous."
Michael Kim (Read More)

Updates 

Page 38:
The note that reads:
Note that the .beam file generated will no longer be portable across platforms.

Should instead read:
Note that the .beam file generated will contain both native and non-native code, and the native part will not be portable across platforms.

Page 62::
n × n – 1 × n – 2 × ... × 1
Should be:
n × (n – 1) × (n – 2) × ... × 1
in order to respect operator precedence.

Page 128:
'gb_trees:enter/2' should be 'gb_trees:enter/3'

Page 138:
The link to http://dslab.epfl.ch/pubs/crashonly/ should be http://dslab.epfl.ch/pubs/crashonly.pdf, as the page has moved.

Page 153:

1. A message to store food is sent from you (the shell) to the fridge process.
...
3. The fridge stores the item and sends ok to your process.

Should be:

1. A message to take food is sent from you (the shell) to the fridge process.
...
3. The fridge removes the item and sends it to your process.

Page 154:

1. A message to store food is sent from you (the shell) to an unknown process.

Should be:

1. A message to take food is sent from you (the shell) to an unknown process.

Page 188:
In the block of code at the bottom of the page, the error which reads:
error:function_clause -> %% not in {{D,M,Y},{H,Min,S}} format
false

Should instead read:
error:function_clause -> %% not in {{Y,M,D},{H,Min,S}} format
false

Page 224:
The text mentions the value:
{next_state, NextStateName, hibernate}

The value should instead be:
{next_state, NextStateName, NextStateData, hibernate}

Page 269:
In the StartFunc section, the first line mentions "how to start the supervisor." It should instead say "how to start the child."

Page 279:
In the last sentence of the second paragraph, the code which reads:
erlang:apply(M,F,Args++A)

Should instead read:
erlang:apply(M,F,A++Args)

Page 291:
The block of code in the center of the page which reads:
%% The friendly supervisor is started dynamically!
-define(SPEC(MFA),
    {worker_sup,
    {ppool_worker_sup, start_link, [MFA]},
    permanent,
    10000,
    supervisor,
    [ppool_worker_sup]}).

Should instead read:
%% The friendly supervisor is started dynamically!
-define(SPEC(MFA),
    {worker_sup,
    {ppool_worker_sup, start_link, [MFA]},
    temporary,
    10000,
    supervisor,
    [ppool_worker_sup]}).

The block of code at the bottom of the page which reads:
init({Limit, MFA, Sup}) ->
    {ok, Pid} = supervisor:start_child(Sup, ?SPEC(MFA)),
    {ok, #state{limit=Limit, refs=gb_sets:empty()}}.

Should instead read:
init({Limit, MFA, Sup}) ->
    {ok, Pid} = supervisor:start_child(Sup, ?SPEC(MFA)),
    link(Pid),
    {ok, #state{limit=Limit, refs=gb_sets:empty()}}.

Page 292:
The block of code at the bottom of the page which reads:
handle_info({start_worker_supervisor, Sup, MFA}, S = #state{}) ->
    {ok, Pid} = supervisor:start_child(Sup, ?SPEC(MFA)),
    {noreply, S#state{sup=Pid}};

Should instead read:
handle_info({start_worker_supervisor, Sup, MFA}, S = #state{}) ->
    {ok, Pid} = supervisor:start_child(Sup, ?SPEC(MFA)),
    link(Pid),
    {noreply, S#state{sup=Pid}};

Page 307:
The text reads:

This tells OTP that when starting your application, it should call
CallbackMod:start(normal, Args). It will also call
CallbackMod:stop(Args) when stopping it.

It should be changed to:

This tells OTP that when starting your application, it should call
CallbackMod:start(normal, Args). This function's return value will be
used when OTP will call CallbackMod:stop(StartReturn) when stopping your
application.

Page 351:
In the code at the top of the page, the line which reads:
{app, stdlib, [{mod_cond, derived}, {incl_cond, include}]},

Should instead read:
{app, stdlib, [{incl_cond, include}]},

Page 367:
In the code block in the center of the page, the line which reads:
{app, stdlib, [{mod_cond, derived}, {incl_cond, include}]},

Should instead read:
{app, stdlib, [{incl_cond, include}]},

And the text which reads:
"If you’re using pure Erlang code without native compiling with HiPE (a native compiler for Erlang code, which gives somewhat faster code, especially for CPU-bound applications), then that code will be portable."

Should instead read:
"If you’re using pure Erlang code, then that code will be portable."

Page 383
The line which reads:

"Note that closing an accept socket will close that socket alone, and closing a listen socket will close all of the related accept sockets"

Should instead read:

"Note that closing an accept socket will close that socket alone, and closing a listen socket will close none of the related and established accept sockets, but will interrupt currently running calls to accept new ones."

Page 395:
In the last block of code at the bottom of the page, the line that reads:
handle_info({tcp_closed, _Socket, _}, S) ->

Should instead read:
handle_info({tcp_closed, _Socket}, S) ->

Page 402:
In the third paragraph under "Test Generators," the sentence that reads:
"It’s called that because, secretly, the underlying implementation of ?_assert(A == B) is fun() -> ?assert(A,B) end; that is to say, it’s a function that generates a test."

Should instead read:
"It’s called that because, secretly, the underlying implementation of ?_assert(A == B) is fun() -> ?assert(A==B) end; that is to say, it’s a function that generates a test."

Page 406:
some_test2_() should be called some2_test_() in order to run, and a
comma should be added after foreach.

Page 407:
some_tricky_test2_() should be called some_tricky2_test_() in order to
run.

Page 435:
The line of code in the section titled "Implementation Details" which reads:
?MODULE = ets:new(regis, [set, named_table, protected]),

Should instead read:
?MODULE = ets:new(?MODULE, [set, named_table, protected]),

Page 439:
In the paragraph in the center of the page, "Note that we use regis (?MODULE) as the table name here" should instead read "Note that we use regis_server (?MODULE) as the table name here".

Pages 459, 463, 465, 534, 536, and 538:
All instances of the function net_kernel:connect should instead read net_kernel:connect_node

Page 465:
In the last text paragraph, ketchup should be replaced by salad.

Page 466:
In the first paragraph, ketchup should be replaced by salad.
In the sixth paragraph, 15 should be replaced by 16.

Page 467:

The text reads:
By default, the heart-beat delay (also called tick time) is set to 15 seconds, or 15,000 milliseconds.

It should read:
By default, the heart-beat delay is set to 15 seconds, or 15,000 milliseconds. After 4 failed heart-beats, a remote node is considered dead. The heart-beat delay multiplied by 4 is called the tick time.

Page 506:
In the code block in the middle of the page:
{logdir, [all_nodes, master], "./logs/"}.
Should be replaced with:
{logdir, all_nodes, "./logs/"}.
{logdir, master, "./logs/"}.

And the sentence in the second to last paragraph of the page which reads "To truly include all nodes, [all_nodes, master] is required" should instead read: "To truly include all nodes, both all_nodes and master are required."

Page 545:
The first line of code in the middle of the page which reads:
foo(X) when is_integer(X) -> X + 1.
Should end with a semicolon and instead read:
foo(X) when is_integer(X) -> X + 1;