我试图在Clojure中创建一个多元函数,如果给定一个向量参数,则只将另一个函数应用于向量;如果给定一个向量加上一个或多个函数,则在向量上映射这些函数的组合,然后应用第三个函数。但不知怎的,我似乎无法在第一个之外访问任何可选参数。
玩具示例代码:
(defn times2 [num] (* 2 num))
(defn square [num] (* num num))
(defn plusfiveall [vec-of-nums] (map #(+ 5 %) vec-of-nums))
(defn toynums
([vec-of-nums]
(plusfiveall vec-of-nums))
([vec-of-nums & [funcs]]
(let [moremath (comp funcs)]
(plusfiveall (map moremath vec-of-nums)))))
我认为应该发生什么:
(toynums [1 2 3])
= (6 7 8)
(toynums [1 2 3] times2)
= (7 9 11)
(toynums [1 2 3] times2 square)
= (7 13 23)
虽然这些示例中的前两个按预期工作,但第三个示例无法应用square
:相反,我得到(toynums [1 2 3] times2 square)
- > (7 9 11)
为了深入研究这个问题,我还尝试了没有映射的版本,并且有着同样令人惊讶的行为:
(defn comp-nomap
([num] (plusfive num))
([num & [funcs]]
(let [funmath (comp funcs)]
(plusfive (funmath num)))))
按预期 (comp-nomap 3)
= 8
(comp-nomap 3 times2)
= 11
但(comp-nomap 3 times2 square)
也= 11,而不是23应该是。
帮助?谢谢!
答案 0 :(得分:2)
这种结构产生了预期的答案:
(defn toynums
([vec-of-nums]
(plusfiveall vec-of-nums))
([vec-of-nums & funcs]
(let [moremath (apply comp funcs)]
(plusfiveall (map moremath vec-of-nums)))))
&
之后的参数会自动收集到一个序列中,这样你就可以使用apply
,这允许comp
函数将序列的内容传递给它作为论据。所以你真的没错,只错过了一件事。这是' varadic'你需要查询的论据。
答案 1 :(得分:2)
你的第二个arity使用varargs的解构,它总是从提供的函数中提取第一个函数。您还需要apply
comp
函数来处理序列中的参数:
(defn comp-nomap
([num] (plusfive num))
([num & funcs]
(let [funmath (apply comp funcs)]
(plusfive (funmath num)))))