带有关键字参数的变量函数

时间:2013-08-26 16:59:01

标签: clojure keyword variadic-functions

我是Clojure的新手,我想知道是否有办法定义一个可以这样调用的函数:

(strange-adder 1 2 3 :strange true)

即,可以接收可变数量的int和关键字参数的函数。

我知道我可以用这种方式用关键字参数定义一个函数:

(defn strange-adder
  [a b c & {:keys [strange]}]
  (println strange)
  (+ a b c))

但现在我的功能只能接收固定数量的整数。

有没有办法同时使用这两种风格?

3 个答案:

答案 0 :(得分:10)

不幸的是,没有。

&解构运算符在参数列表中使用它后面的所有内容,因此它无法在一个表单中处理两组不同的变量arity解构组。

一个选项是将功能分解为多个arities。虽然这只有你可以安排它才有用,所以只有其中一个是可变的(使用&)。更通用且不太方便的解决方案是将整个参数列表视为一个可变参数形式,并从手动开始选择数字。

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

答案 1 :(得分:4)

将可变参数部分移动到参数列表的尾部,并将选项作为地图传递:

(defn strange-adder [{:keys [strange]} & nums] 
  (println strange) 
  (apply + nums))

(strange-adder {:strange true} 1 2 3 4 5)

答案 2 :(得分:1)

我所知道没有正式的支持,但这样的事情应该是可行的:

(defn strange-adder
  [& args]
  (if (#{:strange} (-> args butlast last))
    (do (println (last args))
        (apply + (drop-last 2 args)))
    (apply + args)))

我不知道这是否可以推广(检查关键字?如何扩展到任意数量的最终参数?)。一个选项可能是将所有选项放在一个hashmap中作为最后一个参数,并检查最后一个参数是否是一个hashmap(但这对于某些期望任意参数可能是hashmaps的函数不起作用)。