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.
For more options, visit https://groups.google.com/d/optout.

Reply via email to