aymano.osman
2020-10-10 17:43:43

What is the best way to wrap a function that accepts keyword arguments with a function that provides defaults for some of those arguments?


sorawee
2020-10-10 18:41:22

Here’s one way:

#lang racket (define (g x y #:a a #:b b) (list x y a b)) (define f (make-keyword-procedure (λ (kws kw-args . rest) (keyword-apply g kws kw-args 3 rest #:b 4)))) (f 1 #:a 2) ; '(3 1 2 4)


sorawee
2020-10-10 18:45:57

Ohh, I just saw “default” in your post. I think the above code will not work, since it doesn’t allow overriding the “default” value.


sorawee
2020-10-10 18:46:39

E.g.,

(f 1 #:a 2 #:b 10) fails with:

keyword-apply: keyword duplicated in list and direct keyword arguments: '#:b


sorawee
2020-10-10 18:54:25

Maybe something like this?

#lang racket (require kw-utils/kw-hash-lambda kw-utils/kw-hash) (define (g x y #:a a #:b b) (list x y a b)) (define f (kw-hash-lambda rest-args #:kws kw-hash (apply/kw-hash g (hash-update kw-hash '#:b values 4) rest-args))) (f 1 2 #:a 3) ; '(1 2 3 4) (f 1 2 #:a 3 #:b 5) ; '(1 2 3 5)


badkins
2020-10-10 22:09:48

Why not just the following? (define (g a #:b b #:c c) (list a b c)) (define (f a #:b [ b 7 ] #:c [ c 8 ]) (g a #:b b #:c c))


sorawee
2020-10-11 03:30:34

Well, the above versions could be abstracted out even further:

#lang racket (require kw-utils/kw-hash-lambda kw-utils/kw-hash racket/hash) (define with-default (kw-hash-case-lambda #:kws def-hash [(f) (kw-hash-lambda rest-args #:kws kw-hash (apply/kw-hash f (hash-union kw-hash def-hash #:combine (λ (a b) a)) rest-args))])) (define (g x y #:a a #:b b) (list x y a b)) (define f (with-default g #:b 4)) (f 1 2 #:a 3) ; '(1 2 3 4) (f 1 2 #:a 3 #:b 5) ; '(1 2 3 5)


sorawee
2020-10-11 03:32:38

which is probably the kind of interface that @aymano.osman wants. No repetition of the args.