Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 6
1> List=[1,2,3].
[1,2,3]
2> [First | Rest]=List.
[1,2,3]
3> First.
1
4> Rest.
[2,3]
Functions are first-class values, as you would expect in a functional language. They are defined by a function name and the number
of parameters, using a simple syntax. Here we match the anonymous function to the Square variable. You can then execute it or even create functions that return functions, like the TimesN function in Listing 4.
1> Square = fun(X) -> X*X end.
#Fun<erl_eval.6.13229925>
2> Square(5).
25.
3> TimesN = fun(N) -> (fun(X) -> N*X end)
3> end.
#Fun<erl_eval.6.13229925>
4> lists:map(TimesN(10), [1,2,3]).
[10,20,30]
At the end of Listing 4 you can see a call to the function map in one of the most important Erlang modules: lists.
Normally you define Erlang code in source files with the .erl extension. Each source file can declare a module and which functions are exported or imported to that module. For example,
Listing 5 is a definition of the mymath module, which has two functions -- square and fib.
-module(mymath).
-export([square/1,fib/1]).
square(Value) -> Value*Value.
fib(0) -> 0;
fib(1) -> 1;
fib(N) when N>1 -> fib(N-1) + fib(N-2).
In Listing 5, fib is defined by three different patterns, and the runtime will decide which pattern to call as appropriate. The when ... is a guard clause that can constrain when a pattern is applicable.
Listing 6 shows how to compile and load this module in the shell.
1> c(mymath.erl).
2> mymath:square(5).
25
3> mymath:fib(7).
13
Now that you're at least a little bit comfortable with Erlang, we can begin looking at actors. Three basic elements in Erlang
form the foundation for concurrency. First, the built-in spawn function creates a new process executing a function and returns the new process's process identifier. Second is a syntax
for sending a message to a process with the ! operator. And finally, actors can use a receive...end function to pattern-match messages from the actor's mailbox.
To see how these pieces fit together, we'll create a process that does conversions between Celsius and Fahrenheit temperatures. First we must define the function that the process will run, as shown in Listing 7.
temperatureConverter() ->
receive
{toF, C} ->
io:format("p C is p Fn", [C, 32+C*9/5]),
temperatureConverter();
{toC, F} ->
io:format("p F is p Cn", [F, (F-32)*5/9]),
temperatureConverter();
{stop} ->
io:format("Stoppingn");
Other ->
io:format("Unknown: pn", [Other]),
temperatureConverter()
end.
This function receives messages in the form of three possible tuple formats. The first format is {toF, C}. In this tuple, the first element is the toF atom, and the second is the temperature in Celsius. In the code the variable C is matched to the value. On match, it prints the answer and calls back to this function again. This is a tail-recursive call. Erlang actor functions often follow this idiom of matching an incoming message, then making a tail-recursive call back
to the same function. State can be maintained in the actor by passing it in a function parameter and modifying it on the recursive
call.