#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))))