Erlang: if or case of
The last few weeks I started to learn Erlang, a functional programming language designed to be very solid. This is my first functional programming language I am really learning. At the university I had a small look at Haskell, but I was never really interested in it.
After writing my first few lines of code, the following question came to my mind: when do we use case of and when do we use if? In traditional non-functional programming languages the difference was clear. But the differences blur in functional languages. So what would you write, and why? Given the following example:
case is_pid(Pid) of
true ->
Pid ! {send, ["QUIT :", ?QUITMSG]},
Pid ! quit;
false ->
ok
end
Or
if
is_pid(Pid) ->
Pid ! {send, ["QUIT :", ?QUITMSG]},
Pid ! quit;
_ -> ok
end
Personally I would prefer the second variant, since one can see on the first look what which branch does. What do you think, and why?
Oh my god! Six comments!
Jeena Paradies wrote
In the first one the expression is only evaluated once and then it's up to pattern matching. In the second one the expression in every row is evaluated and yeah it's not a real problem here but I like pattern matching.
In my head the is_pid(), or similar functions, have different cases, that is why it feels naturally to use case of. The second one seems odd, because you think "ok is_pid() returns true .. but wait there is another true, wtf?!" before you remember that it stops evaluating when the first one evaluates to true.
Another thing is that the second one seems like sequential programming "first check row 1 if it is true then ..." the case of is more like a tree which runs only the branch which is necessary.
I'm sorry I don't have a more academic answer, I hope somebody else does.
Tim wrote
I'd prefer the case construct because I like seeing explicit comparisons to explicit values, in this case the true and false pattern matching clauses. The catch-all clause in the if construct is to much indirection for my taste. In functional languages I tend to be more explicit and declarative.
I've got not so much experience reading Erlang code. But isn't there a third possibility, using guards?
Christian Kruse wrote
Hm, after trying it a guard with a function seems to be very elegant:
And later simply call
send_quit(Pid)Jeena Paradies wrote
That looks nice, I'd go with that.
Jeena Paradies wrote
But don't forget to add the other case
send_quit(_) -> ok;otherwise you'll get an exception if Pid is not a pid.Christian Kruse wrote
Yes, of course :-)