Clojure的不断和地图功能
问题描述:
为什么这一点的Clojure代码:Clojure的不断和地图功能
user=> (map (constantly (println "Loop it.")) (range 0 3))
产量输出:
Loop it.
(nil nil nil)
我希望它打印出“循环播放”三倍侧三次评估功能的效果。
答
constantly
不评估其参数多次。这是一个函数,而不是一个宏,因此在运行constantly
之前,参数只被计算一次。所有constantly
确实是需要的(评价)的说法,并返回每次被称为时间返回给定值的函数(无需重新评估什么,因为,正如我所说,constantly
运行之前的说法已经被评估)。
如果您只想对该范围内的每个元素调用(println "Loop it")
,则应该将其作为映射函数传递,以代替constantly
。请注意,您实际上必须将其作为函数传递,而不是评估表达式。
答
你可以通过USIG repeatedly和lambda表达式靠近你的意图的行为。
例如:
(repeatedly 3 #(println "Loop it"))
除非你在REPL,这需要由一个dorun
或类似的包围。 repeatedly
是懒惰的。
答
由于sepp2k正确地指出constantly
是一个函数,所以它的参数将只计算一次。
惯用的方式来实现,你在这里做什么是使用doseq
:
(doseq [i (range 0 3)]
(println "Loop it."))
或可替代dotimes
(因为你实际上并没有使用其在该特定情况下多了几分简洁高效)由range
产生的序列:
(dotimes [i 3]
(println "Loop it."))
这些解决方案的两者都是非延迟,这可能是你想要什么,如果你是刚刚运行的副作用,一些代码。
瞥源。这看起来像赢家。 – Mike 2012-07-23 13:10:45
试图不断使用,以避免显式传递我不需要的参数。虽然会解决这个问题。 – Mike 2012-07-23 13:18:39
请注意,如果你只是想副作用,你应该使用'doseq'或'dotimes'。由于'map'是懒惰的,除非你用'doall'或'dorun'强制执行,否则你不会得到你想要的结果。 – 2012-07-23 15:18:39