clojure:使用循环正确地将内容传递给向量?
我很难理解如何将一些简单的代码抽象成循环/映射/for结构。我有以下代码可以工作,从某种意义上说,它给了我想要的输出: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
(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有一个很好的有意义的名字
。我现在就不谈了,因为这不是问题的核心。