java - 将 Java 翻译成 Clojure - 添加到列表并返回列表

标签 java clojure functional-programming

我想将以下 java 翻译成地道的 clojure:

List<SimpleRecord> recs = new ArrayList<SimpleRecord>();
ParquetReader<SimpleRecord> reader = null;
    try {
      PrintWriter writer = new PrintWriter(Main.out, true);
      reader = new ParquetReader<SimpleRecord>(new Path(input), new SimpleReadSupport());
      for (SimpleRecord value = reader.read(); value != null; value = reader.read()) {
        //value.prettyPrint(writer);
        //writer.println();
        recs.add(value);
      }
      return value;
    } finally {
      if (reader != null) {
        try {
          reader.close();
        } catch (Exception ex) {
        }
      }
    }

但是我在每一步都无法将元素推送到列表中。 这是我现在拥有的:

(let [rows   (vector)
      reader (new parquet.hadoop.ParquetReader (new org.apache.hadoop.fs.Path "file.pq") 
                                               (new SimpleReadSupport))]
  ;reader  
  (try   
    (for [value (.read reader) :while (not (nil? value))]
      (conj value rows)) ;y u no recur?
    rows
    (finally (.close reader)))
  )

但我不知道在 for 中执行此操作的惯用方式是什么。我猜我必须使用 reduce 不?谢谢

最佳答案

对 parquet 或您正在尝试做的事情一无所知,这是我的最佳猜测和一些观察结果:

(with-open [reader (parquet.hadoop.ParquetReader. 
                     (org.apache.hadoop.fs.Path. "file.pq") 
                     (SimpleReadSupport.))]
  (doall (for [value (repeatedly #(.read reader))
               :while value] 
           value))

nilfalse 是假的,其他都是真的,如果 value 永远不会是 false 那么就使用 value 而不是 (not (nil? value))。 (额外的陷阱:(Boolean.false) 是真实的,参见 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L2607 :)

一定要是 vector 吗,为什么?此处的代码返回一个 seq,它由 doall 提前实现(在 with-open 范围内,相当于您的 try-finally。)

Clojure 的数据是不可变的,你不需要附加到列表,你告诉它从旧的创建一个新的并让 Clojure 处理细节:-)。一旦设置了 rows 的值,您就无法在代码示例中执行任何操作,没有“变量”。有 可变引用类型,但在这里使用它们是一种不好的形式。从技术上讲,您可以使用循环/递归来实现它,但这里没有理由这样做(可能是性能),而且通常使用惰性序列方法确实有好处。

reduce 不会工作,因为它消除了提前退出的能力,而且这里的输入是一个 java 对象,而 reduce 需要一个 seq-able 的东西,所以你仍然需要找到某种方法来生成惰性序列,而您又回到了原点。

for 不是循环,它是列表理解。它生成惰性值序列。

我不认为 new 是惯用的,我不确定为什么 :-)。不过,它是使用宏生成代码的更好选择。

花时间理解这些概念,它们在实践中非常棒!

关于java - 将 Java 翻译成 Clojure - 添加到列表并返回列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23019516/

相关文章:

JAVA正则表达式模式匹配器replacechall重复输入

java - 在Java中,如果父类有psvm,为什么我们不能使用名称为String的内部类

java - 学习复杂软件包的策略

java - 如何在 Debian 上修复 _JAVA_OPTIONS

clojure - 为什么 Clojure 默认使用上下文类加载器?

clojure - 如何绑定(bind)匹配的 :or to a variable in core. 匹配

scala - Lazy foldRight 提前终止混淆

functional-programming - 应用转换以组合列表中的某些项目

clojure - 使用 reagent 和 re-frame 时,如何在 crud 类型的应用程序中实现撤消和重做?

scala - 基于类的类型参数使用 Poly1 在方法中映射 HList