This seems ok to me. I'm not convinced there are any useful guarantees when an impersonable property has a guard, but I can see that there could be a useful sanity check.
As you may already know: The primitive `make-struct-type-property' procedure can't accept keyword arguments, because there are no keyword arguments at that level, but you can make a wrapper that calls a primitive variant. At Tue, 17 Jul 2012 17:01:50 -0400, Asumu Takikawa wrote: > Hi all, > > I mentioned an issue I had with struct type properties & impersonators > in the promise/c thread, but I figured I should explain this in more > detail. > > Currently, `make-struct-type-property` takes an optional argument which > is the "guard" for the property. This guard is a procedure that checks > the value coming from *users* of a property (via the `struct` form > and #:property keyword). This is useful so that the implementor of a > struct type property can rely on this guard invariant for whatever > internal processing is needed. > > However, the guard can also be the 'can-impersonate symbol. In this > case, there is no guard procedure and the struct type property accessor > (the procedure actually used to obtain the stored value) can be > impersonated. > > i.e., only one of these two are allowed: > > (define-values (prop:widget widget? prop:widget-accessor) > (make-struct-type-property 'widget valid-widget?)) > > (define-values (prop:widget widget? prop:widget-accessor) > (make-struct-type-property 'widget 'can-impersonate)) > > but not both. > > The issue is that there is a use case for having *both* impersonation of > the accessor and a guard. The reason is that there are two interactions > involved in a property: one interaction between the property implementor > and the struct type creator, who provides the initial value using the > `struct` form, and another interaction involving the client who accesses > the property value in an existing structure instance. > > e.g., > (struct a-widget (...) > #:property prop:widget some-widget) ; guarded by `valid-widget?` > > vs. > > (prop:widget-accessor w) ; not guarded, could be redirected > ; by some impersonator > > > The guard protects the property implementor in the former interaction, > whereas the client is the one that is affected by any impersonation of > the property. Since these two interactions aren't necessarily related, > it's still useful to guard the property even if the property can be > arbitrarily impersonated. > > One example where I needed this is to attach impersonator contracts > (i.e., polymorphic contracts) to a method table in the generics > implementation. The table is stored in a struct property and needs to be > impersonatable for contracting. > > However, I don't want to introduce additional code that duplicates the > sanity checking that the guard would guarantee for the initial methods > provided by the implementor of an *instance* of a generic interface. > > *** > > That was my summary of the problem. I propose to change the API a bit to > make it more flexible: `make-struct-type-property` would take a keyword > #:can-impersonate which will control impersonation entirely orthogonal > to the guard argument (which would now be either #f or a procedure). > > I think this API would cover more of the possible use cases than what is > currently available. > > One way to summarize the use of the guard is that with > non-impersonatable properties, it is making a guarantee about what it is > in the property. With impersonatable properties, it can only make a > guarantee about the *initial* value of the property. The latter can > still be useful though. > > Any thoughts? > > Cheers, > Asumu > _________________________ > Racket Developers list: > http://lists.racket-lang.org/dev _________________________ Racket Developers list: http://lists.racket-lang.org/dev