【问题标题】:Variadic function with keyword arguments带有关键字参数的可变参数函数
【发布时间】:2013-08-27 01:37:02
【问题描述】:
我是 Clojure 的新手,我想知道是否有一种方法可以定义一个可以像这样调用的函数:
(strange-adder 1 2 3 :strange true)
即可以接收可变数量的整数和关键字参数的函数。
我知道我可以这样定义一个带有关键字参数的函数:
(defn strange-adder
[a b c & {:keys [strange]}]
(println strange)
(+ a b c))
但现在我的函数只能接收固定数量的整数。
有没有办法同时使用这两种样式?
【问题讨论】:
标签:
clojure
keyword
variadic-functions
【解决方案1】:
很遗憾,没有。
& 解构运算符使用参数列表中它之后的所有内容,因此它无法以一种形式处理两组不同的可变元数解构组。
一种选择是将函数分解为几个参数。尽管这仅在您可以安排它时才有效,因此只有其中一个是可变参数(使用&)。一个更通用且不太方便的解决方案是将整个参数列表视为一种可变参数形式,并手动从它的开头挑选数字。
user> (defn strange-adder
[& args]
(let [nums (take-while number? args)
opts (apply hash-map (drop-while number? args))
strange (:strange opts)]
(println strange)
(apply + nums)))
#'user/strange-adder
user> (strange-adder 1 2 3 4 :strange 4)
4
10
【解决方案2】:
将可变参数部分移动到参数列表的尾部,并将选项作为映射传递:
(defn strange-adder [{:keys [strange]} & nums]
(println strange)
(apply + nums))
(strange-adder {:strange true} 1 2 3 4 5)
【解决方案3】:
据我所知没有正式的支持,但这样的事情应该是可行的:
(defn strange-adder
[& args]
(if (#{:strange} (-> args butlast last))
(do (println (last args))
(apply + (drop-last 2 args)))
(apply + args)))
我不知道这是否可以概括(检查关键字?如何扩展为任意数量的最终参数?)。一个选项可能是将所有选项作为最后一个参数放在一个哈希图中,并检查最后一个参数是否是一个哈希图(但这对于一些期望可能是哈希图的任意参数的函数不起作用)。