Extracting known keywords from make-keyword-procedure

47 views
Skip to first unread message

Sorawee Porncharoenwase

unread,
Dec 27, 2018, 7:46:11 PM12/27/18
to Racket Users
In Python, we can extract known keywords easily:

def f(a, *args, b=2, c=3, **kwargs):
 
return (a, args, b, c, kwargs)

print(f(42, 43, c=44, d=45)) #=> (42, (43,), 2, 44, {'d': 45})

Doing so in Racket is not as easy. 

#lang racket/base

(provide lambda/kw define/kw)
(require racket/list
         (for-syntax racket/base))

(define-syntax-rule (lambda/kw (kws kw-args . rst) body ...)
  (let ([f (λ (kws kw-args . rst) body ...)])
    (define-values (ignored used-kws) (procedure-keywords f))
    (make-keyword-procedure
     (λ (actual/kws actual/kw-args . actual/rest)
       (define-values (used-kws+kw-args left-kws+kw-args)
         (partition (λ (e) (member (car e) used-kws))
                    (map cons actual/kws actual/kw-args)))
       (keyword-apply f
                      (map car used-kws+kw-args)
                      (map cdr used-kws+kw-args)
                      (list* (map car left-kws+kw-args)
                             (map cdr left-kws+kw-args)
                             actual/rest))))))

(define-syntax-rule (define/kw (f . rst) body ...)
  (define f (lambda/kw rst body ...)))

(module+ test
  (require rackunit)
  (define/kw (f kws kw-args #:b b #:c [c 16] #:d [d 32] a . rst)
    (list kws kw-args a b c d rst))

  (check-equal? (f 1 2 #:b 4 #:c 8 #:e 64) '((#:e) (64) 1 4 8 32 (2))))

While I am happy with the above macro, I wonder if this could be a part of `make-keyword-procedure`, so that we can simply use:

  (define g (make-keyword-procedure
             (λ (kws kw-args #:b b #:c [c 16] #:d [d 32] a . rst)
               (list kws kw-args a b c d rst))))

  (check-equal? (g 1 2 #:b 4 #:c 8 #:e 64) '((#:e) (64) 1 4 8 32 (2)))



Reply all
Reply to author
Forward
0 new messages