为什么过滤懒惰的序列并不适用于clojure?

时间:2014-09-24 06:03:03

标签: clojure

我希望使用以下代码

生成小于10的两个倍数
(filter #(< % 10) (iterate (partial + 2) 2))

预期产出:

(2 4 6 8)

但是,出于某种原因,repl只是没有提供任何输出?

但是,下面的代码工作得很好......

(filter #(< % 10) '(2 4 6 8 10 12 14 16))

我理解一个是懒惰序列,一个是常规序列。这就是原因。但是,如果我希望从一个懒惰的序列中过滤掉所有小于10的数字,我怎么能克服这个问题......?

2 个答案:

答案 0 :(得分:9)

(iterate (partial + 2) 2)

是无限序列。 filter无法知道谓词为真的项目数是有限的,所以当你意识到序列时它会永远存在(参见马克答案)。 / p>

你想要的是:

(take-while #(< % 10) (iterate (partial + 2) 2))

答案 1 :(得分:5)

我想我应该注意Diego Basch's answer在其论证中并不完全正确:

  

filter无法知道谓词为真的项目数是有限的,所以它将永远持续下去

为什么filter应该知道一些事情?实际上filter在这种情况下工作正常。可以对延迟序列应用filter并获取另一个延迟序列,表示可能无限过滤数字序列:

user> (def my-seq (iterate (partial + 2) 2)) ; REPL won't be able to print this
;; => #'user/my-seq
user> (def filtered (filter #(< % 10) my-seq)) ; filter it without problems
;; => #'user/filtered
user> 

这里的关键细节是,当实际序列不确定时,人们不应该试图(通过在OP的情况下打印)延迟序列(这样Clojure就知道了)。

当然,此示例仅用于演示目的,您应在此使用take-while,而不是filter