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

clojure:使用循环正确地将内容传递给向量?,clojure,Clojure,我很难理解如何将一些简单的代码抽象成循环/映射/for结构。我有以下代码可以工作,从某种意义上说,它给了我想要的输出: (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 voici

我很难理解如何将一些简单的代码抽象成循环/映射/for结构。我有以下代码可以工作,从某种意义上说,它给了我想要的输出:

(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])
我基本上使用“(映射向量arg1 arg2…)调用来交错3个序列

显然,我需要做最后一步,删除重复调用以进行缩放。问题是,我需要:

 (map vector arg1 arg2 arg2)
我知道如何使用循环的所有方法都会以顺序给出循环的结果:

 (map vector (arg1 arg2 arg3))

重构初始代码的最佳方法是什么,这样我就只有一个函数调用来进行缩放?

我想您正在寻找:

(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)

@等等,我才刚开始!我喜欢Clojure的
apply
:)是的,现在答案更好了:)。另一件我不理解的是,Apple也会让你准备参数。也考虑<代码>(应用Mavavector(对于一些有意义的名称[ 0 1 2 ] ](制作音阶配方音量刻度的一些有意义的名称))-
for
通常比
map
更好,因为你不仅仅是在映射一个已经存在的函数,尽管我没有足够的领域知识来说明这种情况。@amalloy同意,
map-partial
的可读性可能不如
好,特别是如果OP有一个很好的
有意义的名字
。我现在就不谈了,因为这不是问题的核心。