[plt-scheme] structure, procedure, and keyword arg
At Wed, 16 Jul 2008 14:08:07 -0700, YC wrote:
> it seems that the structs marked as procedures cannot accept keyword
> arguments, even if the procedure in prop:procedure does. Is this by design
> or there is a different way to mark struct as keyword procedures?
>
> Thanks,
> yc
>
> > (define-struct *res (filter args)
> #:property prop:procedure
> (lambda (s x #:error (e #f))
> (let ((res (apply (*res-filter s) (cons x (*res-args s)))))
> (if (not e)
> res
> (error 'restriction))))
> )
> > (define color (make-*res (lambda (x enum) (member x enum)) '((red white
> blue))))
> > (color 'black #:error #t)
> ;; => error
> procedure application: expected a procedure that accepts keyword arguments,
> given #(struct:*res #<procedure:...t/valere/res1\
> .ss:10:25> (red white blue)); arguments were: black #:error
This is a bug, and I've been slow to work out the repair. I think I see
a solution, now.
The problem:
When the `prop:procedure' value is an index of a field within the
structure type, then when the field's value is a keyword-accepting
procedure, the structure acts as a keyword-accepting procedure. So far,
so good.
But when the `prop:procedure' value is a "method" --- i.e., a procedure
that accepts a struct instance as its first argument --- then it
doesn't work, as your example illustrates. The root of the problem is
that `prop:procedure' is built into the core, but keyword support
isn't; the core isn't willing to expose a "method" to other layers
(including the keyword layer), because other layers might abuse the
method by applying it to something other than an instance of the
structure type.
The solution, I think:
We can create a new `prop:procedure' structure type property at the
keyword level, and we can change `scheme/base' to export the new one as
`prop:procedure'. Then, the keyword layer will be able see the "method"
and use it as a keyword-accepting procedure, since it's in charge of
`prop:procedure'. (By using `prop:procedure' from the keyword layer,
you implicitly indicate that you trust the keyword layer to call the
method in the right way).
To make this work, though, the keyword-layer `prop:procedure' has to
automatically imply the core `prop:procedure', so that a structure type
can also act as a regular procedure.
So, I need to extend the structure property system with a way for one
property to imply another set of properties before I can fix the bug.
There have been other cases where we wanted a property to automatically
imply other properties, so I think it will be a generally useful
extension.
Matthew