[racket-dev] Error phrasing (error-message overhaul)

From: Ryan Culpepper (ryan at cs.utah.edu)
Date: Tue Jun 19 16:45:48 EDT 2012

On 06/19/2012 01:52 PM, Eli Barzilay wrote:
> About a month ago, Matthew Flatt wrote:
>> I've pushed a first cut at overhauling error messages from
>> `racket/base'.
>
> Two very independent things really bug me, so I'll make two posts.
>
> The new messages look more organized but there was something that
> bugged me which took a while to realize.  I know that there was some
> discussion on this, and even though I've seen it a good number of
> times now, I still find this error extremely to read:
>
>      >  (map car)
>      application: no clause matching given number of arguments
>        procedure: map
>        given number of arguments: 1
>        arguments:
>         #<procedure:car>
>
> (Sidenote: there's a missing "expected" in here.)
>
> Regardless of the meta-point of whether it's the right thing to have
> the error come from `map' or from `application', the bottom line when
> it comes to me debugging code is that for all errors I look for the
> first "xxx:" which in the majority of cases is enough information to
> know what broke, and only later I look for source location and
> possibly the stacktrace.
>
> So having the above error is extremely disruptive to me -- every time
> that it happened I had to force myself to explicitly read all of the
> lines slowly otherwise I always end up missing the name.

I interpret "<who>: <msg>" as meaning "<who> complains that <msg>", 
whereas IIUC you want it to mean "there is a <who> such that <msg>" or 
"look at <who>; <msg>" or something like that.

For procedures, it make sense whether the <who> was "application" or the 
procedure's name, but I understood a secondary goal of the overhaul to 
be to make the first line as constant as possible and move the varying 
information into the fields below.

> Another place where this is a problem is undefined identifiers (and
> now that I think about it I realized that in this case the annoyance
> is not new):
>
>      >  blah
>      reference to undefined identifier
>        identifier: blah
>        context:
>          [...]
>      >  (module foo racket blah)
>      expand: unbound identifier in module
>        in: blah
>        source:
>         stdin::32
>        context:
>         /home/eli/src/plt/collects/racket/private/misc.rkt:87:7
>
> In both of these messages it's hard to immediately find the `blah' --
> worse if I'm unaware of what "expand" is.
>
> I therefore think that it would be *way* better if that first `x:' is
> reserved for the short name, if any, that is most likely to point me
> in the general direction of "the thing that went wrong".

I agree that having "expand" in the error message is not particularly 
helpful. But I think that putting the unbound name as the <who> position 
would be worse according to my interpretation of the first line of an 
error message, because 'blah' can't complain about anything, because 
'blah' doesn't exist.

> In addition, it would be very nice if the line that followes the first
> `x:' starts with the meat of the problem, so "unbound identifier in
> module" is good, "reference to undefined identifier" is slightly
> worse, and "no clause matching given number of arguments" is very bad
> (I need to know what a "clause" is, I see that there's some kind of
> matching involved which completely confuses newbie-me, and there's a
> "given number of arguments" which is indirectly related to the code I
> wrote).

"unbound identifier in module" is slightly wrong. A module can contain 
many unbound identifiers; it's only a problem is one of them is used as 
a reference. Also, due to macros, a problematic reference might not be 
"in [the] module" from the programmer's point of view anyway.

For the other error, I agree that all arity errors should use the same 
message. (Also, it's possible to have 'case-lambda'-like arities without 
any actual 'case-lambda' clauses, using 'procedure-reduce-arity'.)

Ryan

Posted on the dev mailing list.