【问题标题】:Clojure: Return an Iterator for a java for loopClojure:为 java for 循环返回一个迭代器
【发布时间】:2013-04-25 23:24:46
【问题描述】:

假设我在 Java 中有一个 for 循环:

 for(Foo foo : foos){ do_something() }

现在假设我想将此列表迭代转换为惯用的 clojure。最好的方法是什么?我想返回一些我可以使用的东西,比如 foos 集合上的迭代器。

【问题讨论】:

    标签: java for-loop clojure iterator


    【解决方案1】:

    这是错误的。我保留它,以便它为其他人提供有用的信息

    (dorun (map (constantly (do-something)) foos))
    

    Here's the definition of maphere's the definition of constantly

    总之,这将为 foos 中的每个元素调用 do-somethingconstantly 将忽略您传入的任何内容,并按照您的指示去做。

    【讨论】:

    • map 是懒惰的——你必须将它包装在 dorun 中以确保效果实际发生。 doall 是另一种可能性,但它会抓住序列的头部,这在这里是不可取的。
    • @MichałMarczyk 已更改,但我不确定是否应该更改。看他接下来做什么,我发的原来的东西应该是等​​价的吧?
    • 实际上还有一个更重要的问题——(map (constantly (do-something)) ...) 只会在迭代开始之前(do-something) 一次。你需要像(map (fn [_] (do-something)) ...) 这样的东西。
    • 啊,有趣。是的,我已经走了。我会保留这个(除非它被否决),因为你的 cmets 里面有有用的信息。
    • 至于 sn-ps 的等价性(使用(fn [_] ...)),当然可以在map 的调用者中强制执行惰性序列,但如果迭代的全部意义在于在丢弃结果的同时产生一些效果?这将确保效果及时发生的责任——事实上,它们确实发生了——委托给调用者,这感觉有点脆弱。另外,doseq 的性能可能会更好一些,因为它完全消除了惰性 seq 分配(而map 将始终构造它;dorun 然后将其逐个丢弃)。
    【解决方案2】:
    (doseq [foo foos]
      (do-something))
    

    是您的 Java sn-p 的惯用 Clojure 等价物。

    至于返回一个迭代器,Clojure 的集合都是Iterable 和 seqable,所以你可以在 Clojure 和 Java 中以惯用的方式迭代它们。

    【讨论】:

    • 非常感谢。还有一个问题,我习惯了高阶 Perl 函数闭包,我会将迭代器包装成这样:my $func = _build_iterator(); while( my $next_val = $func->() ) { do_something( $next_val) } clojure 的方法是什么?
    • 想法是在将结果返回给用户之前,在一些方便的处理中关闭对 hbase 扫描结果的调用:(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
    • 我看到你发布了一个新问题;我会在那里回答。 (stackoverflow.com/q/16328566 感兴趣的人。)
    猜你喜欢
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2019-09-16
    相关资源
    最近更新 更多