【发布时间】:2013-04-25 23:24:46
【问题描述】:
假设我在 Java 中有一个 for 循环:
for(Foo foo : foos){ do_something() }
现在假设我想将此列表迭代转换为惯用的 clojure。最好的方法是什么?我想返回一些我可以使用的东西,比如 foos 集合上的迭代器。
【问题讨论】:
标签: java for-loop clojure iterator
假设我在 Java 中有一个 for 循环:
for(Foo foo : foos){ do_something() }
现在假设我想将此列表迭代转换为惯用的 clojure。最好的方法是什么?我想返回一些我可以使用的东西,比如 foos 集合上的迭代器。
【问题讨论】:
标签: java for-loop clojure iterator
这是错误的。我保留它,以便它为其他人提供有用的信息
(dorun (map (constantly (do-something)) foos))
Here's the definition of map 和 here's the definition of constantly。
总之,这将为 foos 中的每个元素调用 do-something。 constantly 将忽略您传入的任何内容,并按照您的指示去做。
【讨论】:
map 是懒惰的——你必须将它包装在 dorun 中以确保效果实际发生。 doall 是另一种可能性,但它会抓住序列的头部,这在这里是不可取的。
(map (constantly (do-something)) ...) 只会在迭代开始之前(do-something) 一次。你需要像(map (fn [_] (do-something)) ...) 这样的东西。
(fn [_] ...)),当然可以在map 的调用者中强制执行惰性序列,但如果迭代的全部意义在于在丢弃结果的同时产生一些效果?这将确保效果及时发生的责任——事实上,它们确实发生了——委托给调用者,这感觉有点脆弱。另外,doseq 的性能可能会更好一些,因为它完全消除了惰性 seq 分配(而map 将始终构造它;dorun 然后将其逐个丢弃)。
(doseq [foo foos]
(do-something))
是您的 Java sn-p 的惯用 Clojure 等价物。
至于返回一个迭代器,Clojure 的集合都是Iterable 和 seqable,所以你可以在 Clojure 和 Java 中以惯用的方式迭代它们。
【讨论】:
my $func = _build_iterator(); while( my $next_val = $func->() ) { do_something( $next_val) } clojure 的方法是什么?
(defmethod scan [java.lang.String java.lang.String] [table start-key end-key] (let [scan (Scan. (Bytes/toBytes start-key) (Bytes/toBytes end-key))] (let [scanner (.getScanner table scan)] (doseq [result scanner] (prn (Bytes/toString (.getRow result)) (get-to-map result)))))) 我想返回一个解开行键的迭代器和用尽时返回一个合适的值,例如 nil