[plt-scheme] structure, procedure, and keyword arg

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Jul 21 08:38:17 EDT 2008

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



Posted on the users mailing list.