[erlang-questions] call by value

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Thu May 19 18:23:27 CEST 2011


On Thu, May 19, 2011 at 17:36, Martin Dimitrov <mrtndimitrov@REDACTED> wrote:

> "All calls with variables in Erlang are call by value: all arguments to
> a function call are evaluated before the body of the function is
> evaluated. The concept of call by reference does not exist, ..."

I'll reply even though others have replied and add a bit more flesh.
Suppose we have a function:

f(X) ->
  X + 7.

and we want to call it like this:

f(3 + 5),

now there are two ways the reduction can proceed. Either we first
evaluate the expression and then make the call,

f(3 + 5) ==> f(8) ==> 8 + 7 ==> 15

which is the call-by-value evaluation strategy, or we do it by
substituting in the expression first,

f(3 + 5) ==> (3 + 5) + 7 ==> 8 + 7 ==> 15

which is the call-by-reference evaluation strategy. Erlang is a
Call-by-value (or an eager/strict) language. Clean and Haskell are
good examples of languages that use a variant the call-by-reference
strategy named call-by-need.

You may be confusing the evaluation strategy with whether parameters
are passed by value or by reference. This is an important notion in an
imperative language like Java, C, C++, Go, etc, but in functional
languages pass-by-value is the only thing you can do. Remember though
that in a functional language values are persistent and thus
immutable. Hence, we can get away with reusing the same in-memory
structure over and over again until we change it. And when we do
change it, we can exploit to share as much as possible from the old
structure. We define

L = [1],

with an in-memory representation like this:

{P1} ==> []

where P1 is a pointer to a cell containing the value 1 and ===> is a
pointer and [] is a special value signifying the end-of-list. Now, if
cons it two times:

L2 = [2 | L],
L3 = [3 | L],

We get two lists like this:

{P2} ====\
            {P1} ==> []
{P3} ====/

My ASCII-art hopefully showing how the L2 and L3 lists share the tail.
Immutability like this means we can just pass a reference and that is
as good as having made a copy of the whole data structure. It can be
exploited by your programs giving you some possibilities which are
quite funny to think about. For instance:

X = 3,
L = {X, X}
L2 = {L, L},
L3 = {L2, L2},
L4 = {L3, L3},
L5 = {L4, L4}.

L5 is built in linear time and contains 32 X cells. That is, we just
built an exponentially large data structure in linear time. Also, all
of it references the same X in memory. Yet if we ask for the sum of
the tree-like structure, then we would get the correct answer of 32 *
3.

So in conclusion: everything is passed by value, but where possible,
Erlang will pass by reference due to the immutable behaviour of the
Erlang heap. So the whole question of the passing style
(value/refence) is specific the implementation and not needed to
understand how the language evaluates (everything is pass-by-value).

> I know that variables are not copied when making a function call and are
> copied when sending messages to processes. So why do the authors say all
> calls are call by value? Aren't the function calls actually call by
> reference?

Yes, when you send a message to another process, Erlang has to move
the structure you are sending to the other process. This is because
processes have separate heaps, so you must somehow move the data from
one heap to the other and copying is the quickest/simplest way to do
that. Storing and retrieving data from/to ETS has the same copying.

-- 
J.



More information about the erlang-questions mailing list