[erlang-questions] Calling a Function with Same argument twice

Ulf Wiger ulf.wiger@REDACTED
Wed Oct 14 15:31:25 CEST 2009


sapan shah wrote:
> Hi,
> 
> see the code below.
> ...
> 
> We call temp:start(1), the output is 4. The output should have been 1.

No, 4 is right.

> Here, when start(1) is called, it intern calls
> {element(1, test(1,1), element(2, test(1,1)}

test(2,2) results in two calls to test(1,1),
which each result in two calls to test(0,0), each
incrementing the 'test' object by 1.

> 
> The first call of test(1,1) should recursively evaluate test(1,1) while the
> second call should already use the value returned by the first call.. Is
> this a right thinking???

I assume you're thinking that it would work like:

test(0,0) ->
     put(test, get(test) +1),
     {0,0};
test(X,Y) ->
   Z = test(X-1, Y-1),
   {element(1, Z), element(2, Z)}.

but here you make only one call and reuse the result.
If the test/2 function werer purely functional (i.e. no side-
effects), the two would be equivalent, but here you use get and
put, so it really makes a difference how many times you explicitly
call the function.

Btw, since test/2 returns a two-tuple, the above is of course
equivalent to

test(0,0) ->
     put(test, get(test) +1),
     {0,0};
test(X,Y) ->
   test(X-1, Y-1).

...which is almost equivalent to

test(X,X) when is_integer(X) -> put(test, get(test) +1), {0,0}.

(It differs only slightly in how it fails on erroneous input).

Think twice before using get/put. Also, why wrap the return values
inside a 1-tuple? Remove the tuple, and you can remove some of the
calls to element/2.

But of course it was a contrived example, so I assume the real
problem you're trying to solve is somewhat different?

BR,
Ulf W
-- 
Ulf Wiger
CTO, Erlang Training & Consulting Ltd
http://www.erlang-consulting.com


More information about the erlang-questions mailing list