我想知道如何强制计算一个惰性的函数序列。
例如,如果我有一个返回整数 1 的函数:
test.core=> (fn [] 1)
#<core$eval2480$fn__2481 test.core$eval2480$fn__2481@4163c61>
test.core=> ((fn [] 1))
1
我构造了这些函数的惰性序列:
test.core=> (repeat 5 (fn [] 1))
(#<core$eval2488$fn__2489 test.core$eval2488$fn__2489@76fd6301> ...)
test.core=> (class (repeat 5 '(fn [] 1)))
clojure.lang.LazySeq
如何实际执行序列中的函数?
test.core=> (take 1 (repeat 5 (fn [] 1)))
(#<core$eval2492$fn__2493 test.core$eval2492$fn__2493@46e1e0c8>)
test.core=> (take 1 (repeat 5 '(fn [] 1)))
((fn [] 1))
test.core=> ((take 1 (repeat 5 '(fn [] 1))))
ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn
我已经通读了 如何在 Clojure 中将惰性序列转换为非惰性序列,它建议 doall ...但我不确定结果会走向何方? 我期待 [1 1 1 1 1] 或类似的东西。
test.core=> (doall (repeat 5 (fn [] 1)))
(#<core$eval2500$fn__2501 test.core$eval2500$fn__2501@14e3c50c>...)
test.core=> (realized? (doall (repeat 5 (fn [] 1))))
true
您的问题是您正在返回一系列未计算的函数。您可以按如下方式评估它们:
=> (map #(%) (repeat 5 (fn [] 1)))
(1 1 1 1 1)
map
和repeat
都是懒惰的,但 REPL 或任何其他使用者强制评估至少尽可能多的惰性序列。