[erlang-questions] Re: What atom name to represent a null value
Joe Armstrong
erlang@REDACTED
Sun Feb 28 13:43:27 CET 2010
On Sat, Feb 27, 2010 at 9:54 PM, Masklinn <masklinn@REDACTED> wrote:
> On 27 Feb 2010, at 20:48 , Joe Armstrong wrote:
>>
>> No no no .... ^ 100
>>
>> For three reasons.
>>
>> a) Think types. The type of
>>
>>> foo(1) -> 2;
>>> foo(2) -> 3;
>>> foo(3) -> 1.
>>
>> is int() -> int()
>>
>> But the type of
>>
>>> foo(1) -> 2;
>>> foo(2) -> 3;
>>> foo(3) -> 1.
>>> foo(_) -> undefined.
>>
>> is int() -> int() | 'undefined' (which is a crazy type)
>>
> Actually, it corresponds to the very simple Haskell type
> (Integer -> Maybe Integer). There's nothing crazy about it if it's what
> is needed by the application
Right - unfortunately most code like this follows from a fundamental
misunderstanding of how error handling works in Erlang.
Code with large numbers of functions returning Maybe types is
usually a sign of bad design - I usually limit myself to one top-level
catch and let everything else generate exceptions.
It's also going to be difficult to give an accurate name to foo -
ie it's more difficult to name a 'thing-that-returns-an-integer-or-undefined'
than just 'thing-that-returns-an-integer'
I'm not saying that you shouldn't have Maybe types - but that often
they are a sign of bad design, or worse, a misunderstanding of the
error handling mechanisms.
/Joe
>
>> b) foo(4) has NO VALUE. but if you say foo(4() -> undefined. Then foo(4)
>> HAS a value (namely undefined).
>>
>> The best way to express this in Erlang is as follows:
>>
>> foo(1) -> 2;
>> foo(2) -> 3;
>> foo(3) -> 1;
>> foo(X) -> exit({ebadArgToFoo, X}).
>>
>> This expresses the required relation that foo is oof type int() -> int()
>> and that evaluation foo(4) is illegal and raises and exeception.
>>
>> The the point of exit - it was designed for *exactly* this situation.
>>
> Well not if Tim doesn't want his function to blow up, which was the use case he
> considered.
>
>> Now any good erlang programmer would not write foo like this, they would write
>>
>> foo(1) -> 2;
>> foo(2) -> 3;
>> foo(3) -> 1.
>>
>> And *nothing* else - since evaluating foo(4) will raise an exception and the
>> default exception will be sufficient to identify the error.
>>
> Unless, of course, you don't want an error.
>
>> c ) There is also a worse problem. If you use the following:
>>
>>> foo(1) -> 2;
>>> foo(2) -> 3;
>>> foo(3) -> 1.
>>> foo(_) -> undefined.
>>
>> Then calling foo(4) will not cause the program to crash *immediately* but
>> somewhat later. For example, suppose you write this:
>>
> Or it won't cause the program to crash at all because at some point when
> the result is needed it will be matched against `undefined` and a specific
> operation will be performed based on that knowledge.
>
> I'm on Robert's side in this case: whether or not this "pattern" should be
> applied depends on the application and the semantic meanings of the function
> call.
More information about the erlang-questions
mailing list