为什么过滤惰性序列在 clojure 中不起作用?



我希望使用以下代码生成所有小于10的2的倍数

(filter #(< % 10) (iterate (partial + 2) 2))

预期输出:

(2 4 6 8)

然而,由于某种原因,repl只是没有给出任何输出?

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

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

我知道一个是惰性序列,一个是规则序列。这就是原因。但是,如果我想从一个懒惰序列中筛选出所有小于10的数字,我该如何克服这个问题。。。?

(iterate (partial + 2) 2)

是一个无限序列。filter无法知道谓词为真的项数是有限的,所以当你实现序列时,它将永远存在(参见Mark的回答)。

你想要的是:

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

我想我应该注意到Diego Basch的答案在论证中并不完全正确:

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> 

这里的关键细节是,当实际序列不是有限的(所以Clojure知道这一点)时,永远不应该试图实现(在OP的情况下打印)延迟序列。

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

最新更新