2016-03-05 32 views
2

我想在Clojure中创建一个多元函数,如果给定一个单独的向量参数,只是将另一个函数应用于向量;如果给定一个向量加上一个或多个函数,则将这些函数的组合映射到向量上,然后应用第三个函数。但不知何故,我似乎无法访问第一个之外的任何可选参数。作为可选参数作为可选参数在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它应该是。

有帮助吗?谢谢!

回答

2

你的第二个arity使用可变参数的解构,它总是会从提供的函数中提取第一个函数。您还需要将applycomp函数转换为序列中的参数:

(defn comp-nomap 
    ([num] (plusfive num)) 
    ([num & funcs] 
    (let [funmath (apply comp funcs)] 
     (plusfive (funmath num))))) 
+0

大声思考,以确保我得到它...我的原始版本破坏了其余的&论点进入函数的方式?所以当我尝试'(comp-nomap 3 times2 square)'时,它看到了'(times2 square)'作为&参数,拔出第一个并将它分配给'func',丢弃其余的......是那个权利? –

+0

是的,这是正确的。 –

+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功能具有的内容序列作为参数传递给它。所以你真的没错,只是错过了那件事。这是你需要查找的'变化'的论点。

+0

谢谢!同样的策略也适用于我更小的玩具示例。你能解释为什么吗?我开始怀疑,答案涉及解构的奥秘,我根本不明白它...... –