我无法弄清楚如何将一些简单的代码抽象为循环/贴图/结构。我有以下代码可以工作,从某种意义上说它给了我想要的输出:
(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?
答案 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)