[plt-scheme] mutual recursion in contracts
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