The easiest way I know is to use `curry`, since Alexis fixed its keyword argument support <https://github.com/racket/racket/commit/d1b8ecb3e0edab3ac455486802646b930e88677f> last year:
#lang racket (define (fish #:name [name #f] #:color [color #f] #:studio [studio #f] #:eyes [eyes 2]) (~a "The fish " name " is " color ", appears in a movie from " studio " and has " eyes " eyes.")) (define disney-fish (curry fish #:studio "Disney")) (disney-fish #:name "Nemo" #:color "orange") … but it might be useful to have some other library functions for this sort of thing: maybe a "curry once" or something like the `adjust-keyword-default <https://github.com/racket/slideshow/blob/master/slideshow-lib/slideshow/widescreen/base.rkt>` used in the `#lang slideshow` implementation. -Philip On Wed, Jul 10, 2019 at 1:25 PM Jens Axel Søgaard <jensa...@soegaard.net> wrote: > Consider the following fishy example wherein we try to > reuse a function with keyword arguments. > > > (define (fish #:name [name #f] > #:color [color #f] > #:studio [studio #f] > #:eyes [eyes 2]) > (~a "The fish " name " is " color ", appears in a movie from " studio " > and has " eyes " eyes.")) > > Let's check see an example: > > > (fish #:name "Nemo" #:color "orange" #:studio "Disney") > "The fish Nemo is orange, appears in a movie from Disney and has 2 eyes." > > A few examples later one quickly realizes that Disney has > a lot of fish in their movies: > > > (fish #:name "Nemo" #:color "orange" #:studio "Disney") > (fish #:name "Dory" #:color "blue" #:studio "Disney") > (fish #:name "Marlin" #:color "orange" #:studio "Disney") > (fish #:name "Wanda" #:color "gold" #:studio "MGM") > (fish #:name "Blinky" #:color "orange" #:studio "Fox" #:eyes 3) > > > No worries, we can quickly define a disney-fish that simply > calls fish using the #:studio keyword and passes other keywords > along. The new disney-fish must accept the same keywords as fish > (except for the studio one), so procedure-reduce-keyword-arity > is needed to restrict the accepted keywords. > > > (define disney-fish > (let () > (define (make-disney-fish kws kw-args . rest) > (keyword-apply/sort fish kws kw-args rest #:studio "Disney")) > > (define-values (fish-required fish-allowed) (procedure-keywords fish)) > (define fish-arity (procedure-arity fish)) ; number of by-position > arguments > > (procedure-reduce-keyword-arity > (make-keyword-procedure make-disney-fish) > fish-arity > (remove '#:studio fish-required) > (remove '#:studio fish-allowed)))) > > Now we can write: > > (disney-fish #:name "Nemo" #:color "orange") > > The new disney-fish accepts only keywords accepted by fish, > so any error reporting works as expected. > > But ... the above solution wasn't quick - it took more work than I > initially expected. > Am I missing something that makes reusing functions accepting > keyword arguments easier? > > /Jens Axel > > > -- full example -- > > > #lang racket > > (require kw-utils/keyword-apply-sort) > > (define (fish #:name [name #f] > #:color [color #f] > #:studio [studio #f] > #:eyes [eyes 2]) > (~a "The fish " name " is " color ", appears in a movie from " studio " > and has " eyes " eyes.")) > > (fish #:name "Nemo" #:color "orange" #:studio "Disney") > (fish #:name "Dory" #:color "blue" #:studio "Disney") > (fish #:name "Marlin" #:color "orange" #:studio "Disney") > (fish #:name "Blinky" #:color "orange" #:studio "Fox" #:eyes 3) > > (define disney-fish > (let () > (define (make-disney-fish kws kw-args . rest) > (keyword-apply/sort fish kws kw-args rest #:studio "Disney")) > (define-values (fish-required fish-allowed) (procedure-keywords fish)) > (define fish-arity (procedure-arity fish)) ; number of by-position > arguments > (procedure-reduce-keyword-arity > (make-keyword-procedure make-disney-fish) > fish-arity > (remove '#:studio fish-required) > (remove '#:studio fish-allowed)))) > > > (disney-fish #:name "Nemo" #:color "orange" > #:studio "foo") > > ; Notes: > ; > (disney-fish #:name "Nemo" #:color "orange" #:studio "Disney") > ; correctly shows error (#:studio not expected) > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/racket-users/CABefVgyXzWW1WJjC9SViyzsheswJD9Ek4LDfwqaNg_v4mT6y%3DQ%40mail.gmail.com > <https://groups.google.com/d/msgid/racket-users/CABefVgyXzWW1WJjC9SViyzsheswJD9Ek4LDfwqaNg_v4mT6y%3DQ%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/CAH3z3ga2mADZ9j9Z2xcTez%3DFM1R4VA%2BLoDuSpdWWrnFHEXWayw%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.