Consider the following code:
1... f(X) -> 2... Y = g(X), 3... h(Y, X), 4... p(Y), 5... f(12).
f(X) ->
case g(X) of
true -> A = h(X), B = 7;
false -> B = 6
end,
...,
h(A),
...
If the true branch of the form is evaluated, the variables A
and B become defined, whereas in the false branch only B
is defined.Whether or not this an error depends upon what happens after the case function. In this example it is an error, a future reference is made to A in the call h(A) - if the false branch of the case form had been evaluated then A would have been undefined.
Suppose we have defined the following:try:foo(1) evaluates to hello.-module(try). -export([foo/1]). foo(1) -> hello; foo(2) -> throw({myerror, abc}); foo(3) -> tuple_to_list(a); foo(4) -> exit({myExit, 222}).
try:foo(2) tries to evaluate throw({myerror, abc}) but no catch exists. The process evaluating foo(2) exits and the signal {`EXIT',Pid,nocatch} is broadcast to the link set of the process.
try:foo(3) broadcasts {`EXIT', Pid, badarg} signals to all linked processes.
try:foo(4) since no catch is set the signal {`EXIT',Pid,{myexit, 222}} is broadcast to all linked processes.
try:foo(5) broadcasts the signal {`EXIT',Pid,function_clause} to all linked processes.
catch try:foo(1) evaluates to hello.
catch try:foo(2) evaluates to {myError,abc}.
catch try:foo(3) evaluates to {`EXIT',badarg}.
catch try:foo(4) evaluates to {`EXIT',{myExit,222}}.
catch try:foo(5) evaluates to {`EXIT',function_clause}.
f(X) ->
case catch func(X) of
{`EXIT', Why} ->
... error in BIF ....
........ BUG............
{exception1, Args} ->
... planned exception ....
Normal ->
.... normal case ....
end.
func(X) ->
...
func(X) ->
bar(X),
...
...
bar(X) ->
throw({exception1, ...}).
...
If a call is made to Mod:Func(Arg0,...,ArgN) and no code
exists for this function then
undefined_call(Mod, Func,[Arg0,...,ArgN])
in the module error_handler will be called.
The code in error_handler is almost like this:
-module(error_handler).
-export([undefined_call/3]).
undefined_call(Module, Func, Args) ->
case code:if_loaded(Module) of
true ->
%% Module is loaded but not the function
...
exit({undefined_function, {Mod, Func, Args}});
false ->
case code:load(Module) of
{module, _} ->
apply(Module, Func, Args);
false ->
....
end.
By evaluating process_flag(error_handler, MyMod) the user
can define a private error handler. In this case the
function:MyMod:undefined_function will be called instead
of error_handler:undefined_function.
Note:This is extremely dangerous
-module(m).
-export([start/0,server/0]).
start() ->
spawn(m,server,[]).
server() ->
receive
Message ->
do_something(Message),
m:server()
end.
When the function m:server() is called then a call is made
to the latest version of code for this module.If the call had been written as follows:
server() ->
receive
Message ->
do_something(Message),
server()
end.
Then a call would have been made to the current
version of the code for this module.Prefixing the module name (i.e. using the : form of call allows the user to change the executing code on the fly.
The rules for evaluation are as follows:

"C" should check return value from read. See p.259 in the book for more info.
ask(Server, Question) ->
Ref = make_ref(),
Server ! {self(), Ref, Question},
receive
{Ref, Answer} ->
Answer
end.
server(Data) ->
receive
{From, Ref, Question} ->
Reply = func(Question, Data),
From ! {Ref, Reply},
server(Data);
...
end.
sum([H|T]) ->
H + sum(T);
sum([]) ->
0.
Note that we canot Evaluate '+' until both its arguments are known.
This formulation of
sum(X) evaluates in
space O(length(X)).The second is a tail recursive which makes use of an accumulator Acc:
sum(X) ->
sum(X, 0).
sum([H|T], Acc) ->
sum(T, H + Acc);
sum([], Acc) ->
Acc.
The tail recursive
formulation of sum(X).
Evaluates in constant
space.Tail recursive = the last thing the function does is to call itself.
For example:
server(Date) ->
receive
{From, Info} ->
Data1 = process_info(From, Info, Data),
server(Data1);
{From, Ref, Query} ->
{Reply, Data} = process_query(From, Query,Data),
From ! {Ref, Reply},
server(Data1)
end.
Note that the last thing to be done in any thread of
computation must be to call the server.