[plt-scheme] mutual recursion in contracts

From: David A. Herman (dherman at ccs.neu.edu)
Date: Fri May 7 16:34:22 EDT 2004

I've noticed that contract expressions are evaluated immediately even 
though they aren't used until later. For example, the following code:

     (define/contract x
       (begin
         (printf "evaluating contract!")
         integer?)
       'foo)

outputs "evaluating contract!" and terminates successfully, but then any 
subsequent reference to x will fail with a contract error.

This makes it hard to create syntactic forms that can produce 
definitions with mutually recursive contracts. Here's a simple example:

     ;; an even is one of:
     ;;   - zero, i.e., (make-even #f)
     ;;   - successor(odd)
     ;; an odd is successor(even)

     (define-type even ([pred (union odd? #f)]))
     (define-type odd ([pred even?]))
     =>
     (define-struct even (pred))
     (provide/contract (struct even ([pred odd?])))
     (define-struct odd (pred))
     (provide/contract (struct odd ([pred even?])))

The above code causes an error because the provide/contract for even 
contains a forward reference to odd?. Of course, I can produce a 
letrec-like form so that I can reorder the expressions in the macro 
template, but in general I'd like to be able to have completely separate 
expressions with mutually recursive contracts.

Clearly, in case contract expressions have side effects, you don't want 
to evaluate them multiple times. So it makes sense to evaluate them 
once. But would it make sense for contract expressions to be evaluated 
lazily, since they aren't needed at the time of the definition? I guess 
that's a little weird.

Anyway, is there a good way for me to work around this? Am I stuck 
having to define a letrec-like form?

Thanks,
Dave


Posted on the users mailing list.