理解:
(for [i (range 5])] i)
...产量:(0 1 2 3 4)
是否有一种惯用的方式来获得(0 0 1 1 2 4 3 9 4 16)(即数字和它们的方块)主要使用 理解?
到目前为止,我找到的唯一方法就是:
(apply concat (for [i (range 5)] (list i (* i i))))
答案 0 :(得分:5)
实际上,如果您考虑为每个值应用每个函数(标识和正方形),则仅使用for
非常简单。
(for [i (range 5), ; for every value
f [identity #(* % %)]] ; for every function
(f i)) ; apply the function to the value
; => (0 0 1 1 2 4 3 9 4 16)
答案 1 :(得分:4)
由于for循环x次,它将返回x值的集合。多个嵌套循环(除非受while
或when
限制)将给出x * y * z * ...结果。这就是为什么外部串联总是必要的原因。
输入和输出之间存在类似的相关关系。但是,如果在map中给出了多个集合,则返回集合中的值的数量是最小集合参数的大小。
=> (map (juxt identity #(* % %)) (range 5))
([0 0] [1 1] [2 4] [3 9] [4 16])
连接map的结果是如此常见的mapcat创建。因此,有人可能会认为mapcat是一种更为惯用的循环方式。
=> (mapcat (juxt identity #(* % %)) (range 5))
(0 0 1 1 2 4 3 9 4 16)
虽然这只是apply concat (map
的简写,但可以轻松创建forcat
函数或宏。
但是,如果需要对集合进行累积,则通常认为reduce是最惯用的。
=> (reduce (fn [acc i] (conj acc i (* i i))) [] (range 5))
[0 0 1 1 2 4 3 9 4 16]
for
和map
选项都意味着遍历集合两次,一次遍历范围,一次用于连接生成的集合。 reduce
选项仅遍历范围。
谨慎分享为什么“主要使用理解”是一项要求?
答案 2 :(得分:2)
我认为你做得对。
使用展平
可以实现略微压缩的方式(flatten (for [i (range 5)] [ i (* i i) ] ))
但我会摆脱 理解,只需使用 interleave
(let [x (range 5)
y (map #(* % %) x)]
(interleave x y))
免责声明:我只是一名业余背包徒步旅行者;)