[erlang-questions] 回复: Is the function call always pass by value?

Richard A. O'Keefe <>
Mon Mar 11 02:41:16 CET 2013


On 11/03/2013, at 2:18 PM, 饕餮 wrote:

> passed by reference?
> This does make sense in my project!
> It's that means It won't change the effect when I use a tail recursion with a record parameter or with no parameter?
> If it pass by value. It may waste a lot of time to copy values…

Consider f(X).

In imperative languages, we distinguish between

 - pass by value:  X is an expression.  It is evaluated in full before the call,
   and during the call it is bound to the formal parameter as if by an assignment
   statement.  This is sometimes called "pass by copy in."

 - pass by reference:  X is a variable.  Its address is determined,
   and in the body of f the formal parameter stands for X, changes to
   the formal parameter being reflected in changes to X.

 - pass by protected reference (Pascal) or const reference (C++): like pass
   by reference but f is not allowed to change its formal parameter.  This
   was added to ISO Pascal to approximate the semantics of pass by value
   for records and arrays with the cost of pass by reference.

 - pass by copy out:  X is a variable.  Its address is determined.
   Inside f, the formal parameter is a local variable.  Changes to
   the formal parameter do not affect X *yet*.  When f returns,
   the value of the formal parameter is assigned to X as if by an
   assignment statement.

 - pass by copy in copy out.  X is a variable.  The formal parameter
   is initialised on entry from its value as if by assignment.  The
   final value of the formal parameter is copied back to X as if by
   assignment.

You will appreciate that since Erlang has no assignment statements,
tuples that cannot be changed, records that cannot be changed, lists
that cannot be changed, and above all no variables that can be changed
after they are bound, most of these parameter passing methods made no
sense in Erlang.

In functional languages, we expect to distinguish between

 - pass by value: X is evaluated in full and bound to the formal parameter
   as if by 'let'-binding.  The value is *NOT* copied.

 - pass by name: the expression X is re-evaluated every time that the formal
   parameter is mentioned.  Algol 60 was the last major language to do this.

 - pass by need: X is passed to f as an unevaluated expression.  The first
   time f needs its value, the expression will be evaluated, and the value
   remembered.  It will not be evaluated again.  Haskell and Clean use this.

Erlang uses pass by value.  Arguments are expressions, they are evaluated
in full, and *values* passed to functions.

It simply is not true that anything is ever passed by reference in Erlang.
Erlang does not have variables that *could* be passed by reference.

Just like Java, Erlang only has pass by reference.
Just like Java, this does *NOT* mean copying anything.

Ignoring function values, you can think of an Erlang value as
*** A POINTER TO THE ROOT OF A TREE ***.
The leaves are numbers, atoms, process IDs, and so on.
The higher levels of the tree are list pairs and tuples (including
records as a special case of tuples).

When we do X = <some expression>, it is this pointer to the root of
a tree that X is set to; the tree as a whole is NOT COPIED.

When we do f(<some expression>), it is this pointer to the root of
a tree that is passed to f; the tree as a whole is not copied.

When we send a message, Pid!<some expression>, the tree *will* be
copied if it is sent to another node, *might* be copied if it is sent
to another process on this node, and might *not* be copied if it is
sent to another process on this node and might be partly copied and
partly not.

Pass by value does NOT imply copying and never has;
copying is only required for mutable data structures,
and Erlang hasn't any.




More information about the erlang-questions mailing list