[erlang-questions] How erlang handle complicated data structure like C?

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Tue Sep 20 17:00:26 CEST 2011


On Tue, Sep 20, 2011 at 16:13, CGS <cgsmcmlxxv@REDACTED> wrote:
> Hi Jesper,
>
> Can you explain why length is a bad idea? I do not deny that matching left
> and right expressions is also a solution, but I see no difference. So,
> please, if you know a bug about length, I am interested in knowing about.

length/1 is not wrong, but note that it has to traverse all of the
list to come up with its answer. In our case, the list is fairly small
(length/1 returns 3), so this may not matter. But for a large list,
the call to length is going to be rather expensive. Contrast this with
a match on the structure which is either [] or [_|_]. This match can
be done simply by examining the head of the list. We don't have to
traverse the list fully to get the answer.

In general, a good idea is to prefer matching over calling length/1 if
you are in doubt. It usually translates to simpler code. Another
worthy point is that matching on lists avoids "Boolean blindness",
which often follows due to a matching on == 3 or similar. Boolean
Blindness is a rather deep concept, but it is worth understanding.
See,

http://existentialtype.wordpress.com/2011/03/15/boolean-blindness/

The exposition could be written in a more approachable way I think,
but I have not gotten around to doing it yet :P

In a certain sense, length/1 tells us _too much_. It yields a number,
namely the length of the list. But we are only interested in two
limited cases, namely sizes 0 and 3. That is, length/1 can be seen as
being too powerful for our cause.

That is, there is nothing wrong with using length/1 here. You should
just know the implications of doing so for other code pieces.

>> 7. How to use the test:
>> receive_function(Packet) when is_my_record(Packet) == true ->
>> do_something_with_my_packet;
>> receive_function(Packet) when is_my_record(Packet) /= true ->
>> I_do_not_care.
>
> You can't do this in Erlang. Guard expressions are limited so you can
> be sure they terminate.
> -------------------
>
> Please, take a better look and you will notice I haven't used guarded
> function for recursion, but for condition. What you said is okay for
> recursion.

The problem is shown in the following silly module:

----
-module(f).

-compile(export_all).

my_own_guard(B) when is_binary(B) -> binary;
my_own_guard(S) when is_list(S) -> list.

f(X) when my_own_guard(X) == binary ->
    binary_to_list(X);
f(X) when my_own_guard(X) == list ->
    X.

---

When we try to compile this in the Erlang shell, it fails:

Eshell V5.8.5  (abort with ^G)
1> c(f).
./f.erl:8: call to local/imported function my_own_guard/1 is illegal in guard
./f.erl:10: call to local/imported function my_own_guard/1 is illegal in guard
error
2>

The relevant part in the reference manual is the part about "Guard Sequences",

http://www.erlang.org/doc/reference_manual/expressions.html#id78951

which states exactly what subset of all expressions that are valid as
a Guard. In particular we are only allowed to call functions in Tables
7.4 and 7.5 and f:my_own_guard/1 is not in that table which is why the
above compilation fail.

It is worth it to contrast this behavior with Haskell, where arbitrary
guard sequences *are* allowed and Haskell is lazy. Or Coq, where are
functions are total, including recursive functions. In these cases,
termination is less of a problem.

> In addition, I didn't say that was the best way to do it, but just an
> example. Jovi needed an example and I gave. I am sorry if my code offended
> you so much to call it "garbage". Feel free to propose the best working idea
> for this case.

Written code is never garbage if it is correct and solves the problem
in an adequate way. Even if it contains minor errors which are not
deep design errors, it isn't a problem - because those are quickly
fixed. To me, that the code is there has a value in its own. This is
mere "golfing" in the sense of producing simpler and smaller code. My
goal was not to show the code to be bad, but rather to show an
alternative way of implementing a solution which I do think is a bit
more idiomatic and functional.

Why? Because I think it is better you see more styles and then form an
opinion of your own about what style you prefer when writing programs.
In any event, consistency tends to win over smug code :) Your style
may be easier to comprehend for a person who is more accustomed to an
imperative code writing style. My style is, perhaps, easier for one
with an ML or Haskell background.

-- 
J.



More information about the erlang-questions mailing list