【问题标题】:Executing a lazy sequence of functions执行惰性函数序列
【发布时间】:2014-02-20 18:00:41
【问题描述】:

我想知道如何强制评估一个惰性函数序列。

例如,如果我有一个返回整数 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

我已经阅读了 How to convert lazy sequence to non-lazy in 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

【问题讨论】:

    标签: clojure lazy-sequences


    【解决方案1】:

    您的问题是您正在返回一系列未评估的函数。您可以按如下方式评估它们:

    => (map #(%) (repeat 5 (fn [] 1)))
    (1 1 1 1 1)
    

    maprepeat 都是惰性的,但 REPL 或任何其他消费者强制至少根据需要对惰性序列进行评估。

    【讨论】:

    • 值得注意的是,序列分块将导致它们以 32 个块为单位进行评估
    • 仅适用于产生分块序列的函数(repeat 不会)。分块有时很重要,但在 OP 弄清楚如何调用函数列表很久之后,它可以安全地被忽略。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    • 2019-04-19
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多