我希望使用以下代码生成小于10的两个倍数
(filter #(< % 10) (iterate (partial + 2) 2))
Run Code Online (Sandbox Code Playgroud)
预期产量:
(2 4 6 8)
Run Code Online (Sandbox Code Playgroud)
但是,出于某种原因,repl只是不提供任何输出?
但是,下面的代码工作得很好......
(filter #(< % 10) '(2 4 6 8 10 12 14 16))
Run Code Online (Sandbox Code Playgroud)
我知道一个是懒惰序列,一个是常规序列.这就是原因.但是如果我希望从懒惰序列中过滤掉所有小于10的数字,我怎么能克服这个问题呢?
(iterate (partial + 2) 2)
Run Code Online (Sandbox Code Playgroud)
是一个无限的序列.filter无法知道谓词为真的项目数是有限的,所以当你意识到序列时它将永远存在(参见Mark的回答).
你想要的是:
(take-while #(< % 10) (iterate (partial + 2) 2))
Run Code Online (Sandbox Code Playgroud)
我想我应该注意到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>
Run Code Online (Sandbox Code Playgroud)
这里的关键细节是,当实际序列不确定时(因此Clojure知道这一点),人们不应该试图实现(通过在OP的情况下打印)延迟序列.
当然,这个例子仅用于演示目的,你应该take-while在这里使用,而不是filter.