> On Aug 29, 2019, at 1:24 PM, Kevin Forchione <
lys...@gmail.com> wrote:
>
> Hi guys,
> I’ve been working for a little while with the idea of being able to pass keyword arguments through a function that doesn’t define them. Additionally I wanted to allow the “pass-through” function to define its own keywords. Additionally didn’t want to have to pre-specify what function might be on the receiving end of the call. But finally, if both pass-through and called functions define the same keywords I didn’t want to have to differentiate between them.
>
> - This seems to involve some combination of make-keyword-procedure and keyword-apply.
> - Since make-keyword-procedure expects a “vanilla” function (one without keywords specified) I decided to define a macro that would wrap the function in a let that with default bindings for each keyword defined by the pass-through. Inside the function I would then assign any values provided by the function call to those variables.
> - Additionally I would build a parameterized list of keywords defined by the pass-through chain. These would be used in conjunction with the keyword list produced by procedure-keywords and the keywords/values captured by the function call to “filter” the lists used by keyword-apply. The idea being to eliminate any keyword/values supplied to the pass-through and defined by the pass-through that were not defined by the called function. This would allow keywords not defined by either to be error by the called function.
>
> As you can see, it’s a convoluted approach and I’m not sure how robust it actually. I’m presenting working code (for my test cases…) but also wondering if someone hasn’t already crated that wheel. :)
A little syntactic sugar makes it appear more palatable with the addition of:
(define-syntax (keyword-apply/filter stx)
(syntax-parse stx
[(_ fn kw kv args)
#'(let ()
(define-values (rkw akw) (procedure-keywords h))
(define-values (Δkw Δkv) (filter/kw (current-caller-kw) akw kw kv))
(keyword-apply fn
Δkw
Δkv
args))]))
And now the definitions are somewhat clearer:
(define (h #:c c . x)
(list c x))
(def (g ((c 0)) . args)
(list c (keyword-apply/filter h kw kv args)))
(def (f ((a 0)(b 0)) n p . ns)
(list kw kv a b n p ns (keyword-apply/filter g kw kv ns)))
Kevin