[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