[plt-scheme] define-struct/contract with super
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