[erlang-questions] How to put a guard?

Serge Aleynikov saleyn@REDACTED
Sat Aug 11 21:30:37 CEST 2007


Jilani Khaldi wrote:
> Hi All,
> I am trying to write a function that returns the position of an element 
> inside a list and the code works "partially", seen I couldn't find a way 
> to obtain what I want:
> position:pos1(a,[e,r,l,a,n,g]). => 4 (ok), but
> position:pos1(k,[e,r,l,a,n,g]). => Error in process <0.30.0> with exit...
> I want it to return 0
> 
> This is the code:
> -module(position).
> -export([pos1/2, pos2/2]).
> 
> % recurion
> % pos1(X, []) -> 0; doesn't work
> pos1(X, [X|_]) -> 1;
> pos1(X, [_|T]) -> 1+position(X,T).

Because of the nature of recursion by the time the whole list is 
scanned, the result already performed N additions, so returning 0 at the 
last step won't be expected result.  You can resolve this with an 
accumulator so that the decision on what needs to be returned performed 
by the last iteration of the function, or throw/catch an exception.

Here's a solution that does what you need:

-module(position).
-export([position/2, p/2, t/2]).

% recursion
p(X, L)       -> catch pos(X, L).
pos(X, [X|_]) -> 1;
pos(X, [_|T]) -> 1+pos(X,T);
pos(_, [])    -> throw(0).

% tail recursion
position(X, L)        -> position(X, L, 1).
position(X, [X|_], N) -> N;
position(X, [_|T], N) -> position(X, T, 1+N);
position(_, [],    _) -> 0.

t(1, F) -> F();
t(N, F) -> F(), t(N-1, F).

Note that throwing an exception as well as traversing call stack adds a 
cost (~ 600 ns/call):

28> F1 = fun()->position:p(a,[e,r,l,a,n,g]) end.
#Fun<erl_eval.20.112921583>
29> F2 = fun()->position:p(k,[e,r,l,a,n,g]) end.
#Fun<erl_eval.20.112921583>
32> F3 = fun()->position:position(a,[e,r,l,a,n,g]) end.
#Fun<erl_eval.20.112921583>
33> F4 = fun()->position:position(k,[e,r,l,a,n,g]) end.
#Fun<erl_eval.20.112921583>
34> Eval = fun(F, N) -> {T, _} = timer:tc(position, t, [N, F])), T/N end.
#Fun<erl_eval.6.72228031>
35> [Eval(F, 100000) || F <- [F1, F2, F3, F4]].
[10.0000,10.6200,9.84999,9.99999]    % mks/call

Serge




More information about the erlang-questions mailing list