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