[plt-dev] Re: [plt-scheme] New contract-related features
On Feb 15, 2009, at 2:24 PM, Matthias Felleisen wrote:
> Could we improve the error message for people who attempt to nest
> regions
>
>> #lang scheme
>>
>> (with-contract f1
>> ((y number?))
>> (with-contract f2
>> ((x boolean?))
>> (define x #t)
>> (define y 1)))
I know about this error, and it's on my list to figure out what's
causing it. I imagine it's something in the expansion. However, one
issue here even if I do fix the problem is that you're defining y
inside the scope of a with-contract but not exporting it, so your
definition should be:
(with-contract f1
((y number?))
(with-contract f2
((x boolean?))
(define x #t))
(define y 1))
Now, whether
(with-contract f1
((y number?))
(with-contract f2
((x boolean?) y)
(define x #t)
(define y 1)))
should work is a good question, and I'm not sure. The problem is that
by the point of the outer with-contract, you've already converted the
definition of y to an inner definition and a rename-transformer bound
to the syntax y, and... yeah. It's nice to just require the
definition being contracted to appear within the with-contract
directly, but I'm not opposed to other ideas about how to handle it.
Note that the following *will* work:
(with-contract f1
((y number?))
(define y
(begin
(with-contract f2
((x boolean?))
(define x #t))
1)))
If you just want to contract x as you use it in y's definition. It's
just the direct with-contract/with-contract nesting that fails, and I
expect it's still some detail of the expansion process that I'm
forgetting to take into account. It should work though, so I do plan
on fixing this, as you might like to do something like the following:
(with-contract f1
((y number?)
(z string?))
(begin
(with-contract f2
((x boolean?))
(define x #t))
(define y 1)
(define z "world")))
Where the internal, protected version of x is available to multiple to-
be-protected
definitions.
I imagine this is due to some lingering issues in expansion. Matthew
helped me out with some before when I was trying to head-expand
everything and helped me realize what I wanted to do, but I didn't get
all of them before I switched over to getting unit contracts
implemented.
> or
>
>> #lang scheme
>>
>> (define (f x)
>> (with-contract
>> f1
>> ((y number?))
>> (define y x)))
>>
>> (f 10)
The error you're getting here is coming from the implicit begin from
the definition, because with-contract forms are not expressions (since
they just define names) and thus the begin still needs one. Your
definition of f doesn't have a body, just the (protected) internal
definition of y.
It's the same error you'd get from something like:
(define (f x)
(define-unit U@
(import)
(export)))
where the internal forms have been expanded completely, in case they
do end up providing at least one body expression, but it turns out
they didn't.
So if you do provide a body expression for f's definition:
(define (f x)
(with-contract
f1
((y number?))
(define y x))
(+ x 3))
(f 10)
it works fine.
Stevie