[plt-scheme] define-struct/contract with super

From: Stevie Strickland (sstrickl at ccs.neu.edu)
Date: Fri Sep 4 18:03:03 EDT 2009

Sorry about not responding to your earlier message.  It's on my queue,  
but hasn't gotten evicted yet.

On Sep 4, 2009, at 5:27 PM, Jon Rafkind wrote:
> Jon Rafkind wrote:
>> define-struct/contract doesn't seem to currently support super  
>> structures as in.
>>
>> (define-struct/contract (my-struct super-struct) (...))
>>
>> For now I used define-struct in a separate module and provide/ 
>> contract'd the sub-struct, but is it possible to make define-struct/ 
>> contract handle super-structs? I saw an email from Arjun in 2005  
>> that attempted this.
>
> I spent a little while trying to make define-struct/contract be able  
> to handle super-structs but don't quite have a solution yet. I think  
> I do understand the issues involved so I wanted to hear what others  
> think about the design.
>
> Currently a contract is put on the struct constructor, make-foo, and  
> it might be hard to get super-constructor's contracts to add in to  
> the sub-struct's constructor. That is if foo is a super-type and bar  
> is a subtype then you need something like
>
> (make-bar foo-field1-contract foo-field2-contract ... bar-field1- 
> contract bar-field2-contract ...)

Right.  In my mind, what you really need is either an extension of the  
existing compile-time information that's bound to the struct name to  
contain the contract references, or at least an additional bit of  
compile-time info in a separate, but easily reconstructable, name.   
The problem with the former is that I hadn't tried doing anything with  
that because a) I haven't looked into what would be required for such  
a change and b) it's not pay-go.  The problem with the latter is that  
other forms, such as struct-out for provide, need to know to export it  
also.

> An alternative seems to be putting the contracts in the guard. If  
> the sub-type checks the contracts for its own values and passes  
> along the super-types values then everything would work fine. If the  
> super-type uses contracts for its own fields then it can check those  
> fields during its own guard procedure. If the super-type doesn't use  
> contracts then the standard define-struct semantics occur.
>
> I haven't implemented contracts in the guard but is there some  
> reason things don't already work this way?

If we allow just immutable structs, then something like this might  
work, since you're guaranteed to get out the values put in during  
construction.  You can't do this for mutable structs, though.  You  
still need, at the very least, contracts on everything but the  
constructor, in addition to the guard situation you've outlined above.

However, that might be enough, may avoid the requirement for carrying  
more information along at compile-time since you're still handling  
construction via the guard, and still get you the guarantees you want.

Of course, there's still problems with define-struct/contract that  
aren't fixed by that (you can still perform unsound operations if, for  
example, you have access to the struct information), which could only  
be fixed by baking contracts into the struct implementation.  But if  
the above works out, at least you'll have made it more useful without  
causing any additional problems.

Stevie


Posted on the users mailing list.