我正在尝试在Clojure中创建一个for.
我正在关注Clojure网站上的作弊表.
例如:
(take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))
Run Code Online (Sandbox Code Playgroud)
我正在尝试创建自己的for应该打印"Hello World"100次.
(take 100 (for [a (range 100)
:while (< a 100)]
(println "Hello World")
)
)
Run Code Online (Sandbox Code Playgroud)
由于某种原因,它不会打印Hello World 100次.为什么不?
Chr*_*erg 12
你需要注意的最重要的事情是,Clojure中的序列是懒惰的.这意味着序列中的项目仅在需要时进行评估.这允许您使用无限序列.
大多数情况下这是你想要的,但是当你对序列项的值不是真正感兴趣时,可能会让人感到困惑,但是在创建序列项的函数的副作用中.在您的示例中,序列由println函数的100个返回值组成,即100次nil- 不是很有趣.但该println功能具有向stdout打印"Hello World"的副作用.
问题是,如果您从未对序列中的项目执行任何操作,println则永远不会评估函数,也不会打印字符串.它在REPL中有效,因为REP中的P代表打印 - 打印您输入的表达式的返回值.要打印整个序列,必须对其进行评估,因此您会看到一堆"Hello World",但也是一堆nils.如果在REPL之外运行代码(不使用返回的值),则不会看到Hello Worlds.
如果您对项目生成功能的副作用感兴趣,可以使用doall或doseq.doall强制评估整个序列并返回它:
(doall (for [a (range 100)] (println "Hello World")))
Run Code Online (Sandbox Code Playgroud)
doseq不返回序列(它返回nil)并具有如下语法for:
(doseq [a (range 100)] (println "Hello World"))
Run Code Online (Sandbox Code Playgroud)
另请注意,您实际上只需提供一次所需的计数(100).该range函数已生成一个包含100个项目的序列.:while代码中的子句是多余的,take函数也是多余的(从包含100个项目的序列中获取前100个项目并不多).
希望这可以帮助!
事实上,它对我有用。最后一个示例确实打印了 100 "Hello World",但是只得到了REPL 中打印的 100 take。nil第一个示例的工作原理如下:
user=> (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))
([1 0] [2 0] [2 1] [3 0] [3 1] [3 2] [4 0] [4 1] [4 2] [4 3] [5 0] [5 1] [5 2] [5 3] [5 4]
[6 0] [6 1] [6 2] [6 3] [6 4] [6 5] [7 0] [7 1] [7 2] [7 3] [7 4] [7 5] [7 6] [8 0] [8 1]
[8 2] [8 3] [8 4] [8 5] [8 6] [8 7] [9 0] [9 1] [9 2] [9 3] [9 4] [9 5] [9 6] [9 7] [9 8]
[10 0] [10 1] [10 2] [10 3] [10 4] [10 5] [10 6] [10 7] [10 8] [10 9] [11 0] [11 1] [11 2]
[11 3] [11 4] [11 5] [11 6] [11 7] [11 8] [11 9] [11 10] [12 0] [12 1] [12 2] [12 3] [12 4] [12 5] [12 6] [12 7] [12 8] [12 9] [12 10] [12 11] [13 0] [13 1] [13 2] [13 3] [13 4] [13 5] [13 6] [13 7] [13 8] [13 9] [13 10] [13 11] [13 12] [14 0] [14 1] [14 2] [14 3] [14 4] [14 5] [14 6] [14 7] [14 8])
对于实际打印,您可以尝试更简单的循环:
(dotimes [i 100] (println "Hello World"))
Run Code Online (Sandbox Code Playgroud)
最后,如果您使用for,则不需要:while,因为该范围已经有 100 个元素:
(take 100 (for [a (range 100)]
(println "Hello World")))
Run Code Online (Sandbox Code Playgroud)