clojure:使用循环正确地将事物传递给向量?

时间:2012-05-05 19:31:57

标签: clojure

我无法弄清楚如何将一些简单的代码抽象为循环/贴图/结构。我有以下代码可以工作,从某种意义上说它给了我想要的输出:

(let    
    [recipe [1 1 2] 
    voicing [0 2 4]
    counts (range (count voicing))
    scale C]
    (map vector
        (make-scale recipe voicing scale 0)
        (make-scale recipe voicing scale 1)
        (make-scale recipe voicing scale 2)
    )

输出是:

 ([:C :E :G] [:D :F :B] [:E :A :C] [:G :B :D] [:A :C :F] [:B :E :G] [:D :F :A])

我基本上使用“(map vector arg1 arg2 ...)”调用来交错3个seqs。

显然我需要做出删除重复调用make-scale的最后一步。问题是,我需要:

 (map vector arg1 arg2 arg2)

以及我知道如何使用循环的所有方法都给出了seq中循环的结果:

 (map vector (arg1 arg2 arg3))

重构初始代码的最佳方法是什么,所以我只有一个函数调用make-scale?

1 个答案:

答案 0 :(得分:3)

我认为你在寻找:

(apply map vector (map (partial make-scale recipe voicing scale) [0 1 2]))

通常,只要有序列并且想要将其元素用作函数的连续参数,apply就会有所帮助。您还可以在列表中添加一些参数(在这种情况下,vector参数作为map的第一个分段被添加。)

在Clojure中,许多stdlib函数需要一个扩展列表(vector和几乎所有其他集合构造函数str。)我认为这是设计的 - 你应该使用apply他们。

有问题的序列甚至可以是无限的(即懒惰无限),当然如果应用的函数处理惰性无限参数列表。即使将concat应用于无限列表列表,这也可以正常工作:

(take 7 (apply concat (cycle [[1 2 3]])))
>>> (1 2 3 1 2 3 1)