[erlang-questions] call by value
Martin Dimitrov
mrtndimitrov@REDACTED
Thu May 19 21:07:34 CEST 2011
Thanks for the explanation. Now I am glad I asked that question.
I had always thought of call-by-value as the actual act of copying the
value which now I understand it might be or might not be as in the case
with Erlang.
Regards,
Martin
On 5/19/2011 7:23 PM, Jesper Louis Andersen wrote:
> 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.
>
More information about the erlang-questions
mailing list