在 Racket 中打包关键字参数?

Packing keyword arguments in Racket?

有没有办法将函数的关键字参数指定为字典,类似于允许我们为位置参数提供列表的 .?我正在寻找类似于 python 的 *args and **kwargs.

的内容

更详细:

如果我们想在函数中处理任意数量的位置参数,我们可以这样定义它:

(define (my-add . args)
  (apply + args))

并将其与可变数量的参数一起使用:

(define numbers '(1 2 3))
(apply my-add numbers) ;=> 6
(define numbers '(1 2 3 4 5))
(apply my-add numbers) ;=> 15

即使对于不通过 . 语法显式处理位置参数的 "rest" 的函数,我们也可以使用 apply 从列表中解压位置参数。

(apply expt '(2 3)) ;=> 8

我看到 apply does forward on keyword argument 除了位置参数。但是,这仅在调用的函数本身标识它期望的特定关键字参数时才有效。例如,在函数本身不使用关键字参数而只是打算将它们转发到某个适当的处理程序的调度情况下,以这种方式使用 apply 不会做我们需要的事情,因为函数需要知道它所分配到的任何函数所接受的所有关键字参数,更不用说在调用处理程序之前以某种方式重新打包它们的工作了。

作为说明问题的具体示例,请考虑一个简单的 "echo args" 函数,该函数回显传递给它的所有参数:

(define (echo-args . args)
  (printf "~a" args))

只有位置参数:

> (echo-args 1 2 5)
(1 2 5)

关键字参数:

> (echo-args 1 2 5 #:key 'hi)
; application: procedure does not accept keyword arguments
;   procedure: echo-args
;   arguments...:
;    1
;    2
;    5
;    #:key 'hi
; Context:
;  /Applications/Racket v7.5/collects/racket/repl.rkt:11:26

是否有内置的方法来完成这种事情?如果没有,关于如何使这项工作有什么想法吗?

您要找的是make-keyword-procedure。这会生成一个接受所有关键字参数的过程,并且可以从 dictionary.Taking 文档中的示例访问:

> (define show
    (make-keyword-procedure (lambda (kws kw-args . rest)
                              (list kws kw-args rest))))
> (show #:blue 3 4)
'((#:blue) (3) (4))

当然,作为两个列表实现的字典可能有点烦人。所以 Alex Knauth 做了一个小包 hash-lambda ,它给你一个更直接的哈希映射,比如 API.