领悟:
(for [i (range 5])] i)
...产量:(0 1 2 3 4)
有没有一种惯用的方法来获得 (0 0 1 1 2 4 3 9 4 16) (即数字及其平方),主要使用for理解?
到目前为止,我发现的唯一方法是:
(apply concat (for [i (range 5)] (list i (* i i))))
领悟:
(for [i (range 5])] i)
...产量:(0 1 2 3 4)
有没有一种惯用的方法来获得 (0 0 1 1 2 4 3 9 4 16) (即数字及其平方),主要使用for理解?
到目前为止,我发现的唯一方法是:
(apply concat (for [i (range 5)] (list i (* i i))))
实际上,for
如果您考虑为每个值应用每个函数(恒等式和平方),则使用 only 非常简单。
(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)
由于 for 循环 x 次,它将返回 x 值的集合。多个嵌套循环(除非受while
or限制when
)将给出 x * y * z * ... 结果。这就是为什么外部串联总是必要的。
输入和输出之间存在类似的相关性,地图。但是,如果在map中给出了多个集合,则返回集合中的值的数量是最小集合参数的大小。
=> (map (juxt identity #(* % %)) (range 5))
([0 0] [1 1] [2 4] [3 9] [4 16])
连接 map 的结果是如此常见的 mapcat 被创建。正因为如此,有人可能会争辩说 mapcat 是一种比 for 循环更惯用的方式。
=> (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
选项仅遍历范围。
愿意分享为什么“主要使用 for 理解”是一项要求?
我认为你做得对。
使用flatten可以实现稍微压缩的方式
(flatten (for [i (range 5)] [ i (* i i) ] ))
但我会摆脱for理解,只使用interleave
(let [x (range 5)
y (map #(* % %) x)]
(interleave x y))
免责声明:我只是一个业余的clojurist ;)