[racket] exn:fail:contract:variable id field

From: Casey Klein (clklein at eecs.northwestern.edu)
Date: Fri Apr 1 10:22:10 EDT 2011

On Fri, Apr 1, 2011 at 7:45 AM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> At Fri, 1 Apr 2011 04:10:19 -0500, Casey Klein wrote:
>> What exactly is in the `id' field of a `exn:fail:contract:variable'
>> structure? It doesn't seem to be the symbolic name of the
>> not-yet-defined variable.
> It's the real symbolic name --- the one that would work with
> `namespace-variable-value' and similar reflective operations.
> In this case, you get `x.6', because the original symbolic name `x' was
> introduced by a macro; the variable name can't be just 'x, since it
> must be renamed for hygiene. Also, the symbol that prints as 'x.6' in
> this case is a kind of gensym --- not the result of `(string->symbol
> "x.6")'.
> The mismtach between `x' and `x.6' reflects is a mismatch between
> identifiers (the modern Scheme way of binding) and symbols (the
> traditional Lisp way of binding, on which the identifier layer is
> currently built and that sometimes shows through in the reflection
> API).

Thanks, that makes sense.

I asked this question because I'm having trouble getting Redex to
produce a good error message when you use a metafunction before its
definition. For example, the program

#lang racket

(require redex)

(define-language L)

 (reduction-relation L (--> (any ...) ((f any) ...)))
 '(a b c))

(define-metafunction L
  [(f any) (any)])

raises the error "reference to an identifier before its definition:
f3.18". I know how to get the error to say "f.18", but I don't know
how to get it to say just "f".

The problem is the expansion of metafunction definitions. The
definition of f expands into something roughly like

  (define f.18 ---)
  (define-syntax f (make-term-fn #'f.18)))

and the reduction-relation macro walks over the rules' right-hand
sides, looking for identifiers bound to term-fns and constructing
appropriate calls to the underlying functions. With this approach, the
apply-reduction-relation call ends up referencing f.18 (in this case,
before it's defined).

Maybe mine is a weird case, but it has me wondering why it's better
for the exn:fail:variable:contract message to use the real symbolic
name. These names are never known to programmers, since they don't
appear in source programs, right?

Posted on the users mailing list.