"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.

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.

"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 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]}).

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

It should be changed to:

This tells OTP that when starting your application, it should callCallbackMod: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]),

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;