[erlang-questions] guards

Witold Baryluk baryluk@REDACTED
Sat Jul 25 19:31:22 CEST 2009


Dnia 2009-07-25, sob o godzinie 18:04 +0100, Dave Pawson pisze:
> Thanks Witold,
> 
> 2009/7/25 Witold Baryluk <baryluk@REDACTED>:
> > Dnia 2009-07-25, sob o godzinie 03:50 +0100, Dave Pawson pisze:
> >> filterHelper(Lst,Int,Result) when ((length(Lst) == 1) and
> >> (lists:nth(1,Lst) =< Int)) ->
> >>     [lists:nth(1,Lst) | Result];
> >
> > filterHelper([Elem],Int,Result) when Elem =< Int ->
> >    [Elem | Result];
> >
> > simpler and a lot faster.
> 
> 
> I'm looking for understanding today,
> not speed!
> 
> Speed will come, but later!
> I did not understand the [A] idea, that it is a list of one element!

Pattern matching is powerful and i hope you would like it :)

so this "simpler" part.

for example if you would like to only match one element lists with,
value like second argument:

filetrHelper([Int], Int, result) ->
 ...

(eventually adding is_integer/1 test)


"a lot faster" for two reasons.

1. compiler knows easier what is here, and extracts first (and only one)
element of the list, and reuse it in the body of function clause.
additionally if you have more clauses, compiler can more easily
find common structure between them and do checks in best possible way.
For example if two of them check if it have length == 1, check will
be done only once, i hope, this is just a theory. In case of guards
compiler probably isn't so smart.

2. I assumed this filterHelper is used in some kind of loop,
so it is for example called N times. What if most times the first
argument of filterHelper is actually big list (with K elements on
avarage?). You will end traversing all this lists (there is no
precomputed length of list, but thanks to this lists are smaller), only
for testing it if it is of some small (1) size. This makes this code
really slow, like N*K operations not just N. If K is large (10 or 100),
this is can be problematic.

This is the reasons why in my mind I see red alert blinking, always when
I find code with length/1 calls in guards. I would be happy
if it would be removed from allowed functions list in guards :)

Eventually it would be nice to have guard of the form length(List, Min,
Max), which would answer, if list List is of size between Min and Max
(or infinity) inclusive. So being equivalence of length(List) >=
Min ,length(List) =< Max, but faster. Only problem I see is with the
"inproper" lists, like [1|2], length throws exceptions for them.
So it is somehow unfortunete that there is no flag if lists is proper
or not. Probably for the same reason that there is no length field.
(or mayby this is because VM is doing some dirty tricks, and lists isn't
really immutable).

-- 
Witold Baryluk <baryluk@REDACTED>



More information about the erlang-questions mailing list