[eeps] Multi-Parameter Typechecking BIFs
mats cronqvist
masse@REDACTED
Mon Feb 23 10:59:02 CET 2009
"Richard O'Keefe" <ok@REDACTED> writes:
> On 20 Feb 2009, at 8:55 pm, mats cronqvist wrote:
>> I think I see what you're saying. Alas, your conclusion seems
>> backwards.
>
> Obviously I don't think so.
>>
>>
>>> Take again the very common case of "this argument is an
>>> {M,F,A} triple".
>>>
>>> Right now, people write out, every time,
>>>
>>> f(...{M,F,A}...)
>>> when is_atom(M), is_atom(F), is_integer(A), A >= 0
>>> -> ...
>>>
>>> Writing this as
>>>
>>> f(...{M::atom,F::atom,A::integer}...)
>>> when A >= 0
>>> -> ...
>>>
>>> (A) Makes it much much harder to *see* the triple.
>>
>> Marginally harder, I'd say. And with syntax haglighting on it would
>> be a non-issue.
>
> "Oops there is a problem here,
> so let us imagine that it has been solved."
you're a very weird guy. (that's a compliment.)
>> But the problem with the current when syntax is exactly that; that
>> you have to split all the conditions in pieces (the first condition
>> being where in the argument the variable is bound.)
>
> Not quite. The current syntax does force you to separate
> the *pattern match* from the *conditions*, but at least it
> lets you write the *conditions* as one thing. Putting ::test
> in a pattern breaks what's logically one condition into lots
> of little apparently unrelated pieces.
Separating the pattern match from the condition is bad. The 'when'
keyword should have never been introduced.
>>> (C) Kicks abstraction in the teeth, beats it in the head with
>>> an iron bar, and steals its notecase.
you're a very weird guy.
>>> Where does it say {M,F,A}::names_a_function?
Mmmm... nowhere?
>>> This is a very very low level way of describing what you want.
If you say so.
[much verbiage about]
> -define(date(D,M,Y),
> is_integer(D), 1 =< D, D =< 31,
> is_integer(M), 1 =< M, M =< 12,
> is_integer(Y), 1900 =< Y, Y =< 2200).
[being better than]
> f(..., {D::integer,M::integer,Y::integer}, ...) -> ...
Meh. This discussion is about
f(..., {D::integer,M::integer,Y::integer}, ...) -> ...
vs.
f(..., {D,M,Y}, ...)
when is_integer(D),is_integer(M),s_integer(Y) -> ...
>>> What we want, of course, is to say that the *whole* triple
>>> satisfies a named condition. And we can do that, right now,
>>> with macros.
Macros. Wonderful. Actually, there is a way to declare types;
-type(date() :: {integer(),integer(),integer()}).
>> But then I have to go looking in a header file somewhere to find the
>> -define(mod_func_arity,...).
>> Yuck.
>
> Yes you do. But at least it is there to be found.
> (Most modern text editors support some kind of tags facility,
but not syntax haghlighting?
> which means that "to go looking" means the enormous burden of
> putting the cursor on the macro call and pressing perhaps as
> many as two keys. As it happens, the text editor I use doesn't
> support tags, so I'd have to type
> <ESC>! find-macro mod_func_arity<ESC>
> Big deal.)
That's fascinating.
>>> Guards are good. I have had the misfortunate to have to read
>>> "Prolog" code written in a dialect that allowed type tests in
>>> patterns. Never again.
>>
>> Type checking in guards sucks. It splits the match condition into
>> pieces, makes it prone to stupid typo errors, and, worst of all,
>> presents a barrier to type checking that is high enough to make
>> people just skip it altogether.
>
> I don't understand why you say "prone to .. typo errors".
> Why is putting type tests in guards any more error-prone than
> putting them into patterns?
because real code (here defined as written by professional
programmers (i.e. people that program from 9 to 5) as opposed to CS
professors) looks like this;
bla(FooBlaBaxBar, FooFooBlaBaxBar, LaDiDaBaxBar, FooFooBlaBazBar,
BlaBlaaBarBar, FooFooBlaBurpBar) ->
when is_integer(FooFooBlaBaxBar), is_atom(FooFooBlaBazBar) ->
> Oddly enough, I would regard type tests in patterns as creating a
> barrier to type checking that would make people skip it altogether.
That is indeed very odd. Almost weird.
More information about the eeps
mailing list