[racket-dev] very unhelpful beginner language error message, possible fix proposed

From: Stephen Bloch (bloch at adelphi.edu)
Date: Mon Feb 13 19:32:12 EST 2012

On Feb 13, 2012, at 5:07 PM, David Van Horn wrote:

> On 2/13/12 4:20 PM, Stephen Bloch wrote:
>> On Feb 13, 2012, at 8:28 AM, David Van Horn wrote:
>>> In BSL, you can detect when the first element of a clause is a variable bound to a function, but I don't follow the reasoning about ISL.  You can't distinguish good from bad uses without running the code because you can't tell if a name refers to a function or a non-function.
>> Not reliably, because the student COULD be using a parameter or a local variable in that position.  But in the COMMON case of this error, the student will use a predefined function or an explicitly user-defined top-level function, and it should be possible to recognize those at syntax-check-time.
> But even if the name is a parameter, it cannot be bound to a function. If it's a local, it either is or isn't a function -- you can tell from the definition.

In ISLL, a parameter could be bound to a function.  You're right, in ISL it can't, so that's even easier.

> I think it's correct to consider this a syntax error, not a run-time error.  It should just have a better message.
>> Which leaves
>>> cond: question result is not true or false: (lambda (a1) ...)
>> as a good error message to report at run time in the rare cases that don't match the above description.
> Except you don't want to say lambda in BSL.

No, of course not.

So to sum it up:

In BSL and BSLL, you can tell at compile-time what identifiers are bound to functions (either predefined or user-defined-at-the-top-level).  If the first element of a cond-clause is such an identifier, trigger our clever-error-message-to-be-determined.

In ISL, there's an additional case: a local variable might or might not be bound to a function.  That's a little more hassle to check, but it should be doable at compile-time.  Again, if the first element of a cond-clause is an identifier bound to a function, trigger our clever error message at compile-time.

In ISLL, there's another additional case: a parameter, for which you REALLY can't tell (without a bunch of heavy-duty type inference, and in general it's probably undecidable) whether it's bound to a function.  In that case, you can use the aforementioned run-time error message involving lambda.  In all the previous cases, which we should still be able to detect and which should cover the great majority of cases, trigger the clever compile-time error message.

In ASL and #lang racket, there are still cases in which you could trigger this error message.  There's already a mechanism to tell whether a particular variable is ever mutated in a particular module (I don't remember what this is used for, but people have mentioned adding a "set!" as a work-around to various provide/require problems), so if the cond-clause-entry in question is an identifier that isn't mutated in this module and is bound to a function, trigger the clever error message.  Although for ASL and #lang racket, the clever error message isn't as important....

Stephen Bloch
sbloch at adelphi.edu

Posted on the dev mailing list.