如何在Java中实现clojure ISeq?

时间:2018-02-27 12:44:13

标签: java collections clojure

我想向Clojure传递Java函数的映射。这些函数使用实现IFn接口的Java匿名类。我还需要实现ISeq接口来传递列表。 ISeq界面很简单但有no documentation。我需要知道ISeq中的每个方法做了什么和/或找到实现所有ISeq方法的类的Java代码(我不希望{C {{}到Clojure结构)。

2 个答案:

答案 0 :(得分:1)

  

我需要知道ISeq中每个方法的作用

您还应该了解它扩展的接口:

public interface Seqable {
    ISeq seq(); // returns an ISeq instance
}

public interface IPersistentCollection extends Seqable {
    // returns the count of this coll
    int count();
    // returns a new coll with o cons'd onto it
    IPersistentCollection cons(Object o);
    // returns a new empty coll (of same type?)
    IPersistentCollection empty();
    // compares this coll against o for equality
    boolean equiv(Object o);
}

public interface ISeq extends IPersistentCollection {
    // returns the first item in this seq
    Object first();
    // returns a new seq of every item in this except the first
    ISeq next();
    // returns a new seq of every item in this except the first
    // ASeq returns empty for empty
    ISeq more();
    // returns a new seq with o cons'd onto this seq
    ISeq cons(Object o);
}
  

...或者找到实现所有ISeq方法的类的Java代码

ASeq abstract class implements (most of) ISeq。扩展ASeq implement ISeq.next()

的类

除了重新实现ISeq之外,确实更容易实现目标。也许看看Clojure的Java实现会给你一些想法。

答案 1 :(得分:1)

问题文本的这个片段似乎表明在数组上调用seq,这是关于将Java数组转换为Clojure seqs的问题的链接答案,建议将数组的内容复制到一个新的SEQ:

  

(我不想copy my lists到Clojure结构)

这是的情况。相反的是,seq返回由数组支持的包装器seq,如以下REPL交互所证明的那样:

Clojure 1.9.0
user=> (def xs (object-array [:foo :bar]))
#'user/xs
user=> (seq xs)
(:foo :bar)
user=> (def s1 (doall (seq xs)))
#'user/s1
user=> s1
(:foo :bar)
user=> (aset xs 0 :quux)
:quux
user=> (seq xs)
(:quux :bar)
user=> s1
(:quux :bar)

请注意,改变底层数组会导致对突变之前创建的数组上的seq进行可观察的更改。

这与seq传递的java.util.List行为形成鲜明对比,ISeq同时不是Clojure 1.9.0 user=> (def ys (java.util.ArrayList. [:foo :bar])) #'user/ys user=> ys [:foo :bar] user=> (def s2 (seq ys)) #'user/s2 user=> s2 (:foo :bar) user=> (.set ys 0 :quux) :foo user=> ys [:quux :bar] user=> s2 (:foo :bar) ,在这种情况下,确实会分配一个新的seq:

Iterable

这不一定是一个可怕的结果,因为seq会被分块,但避免任何包装可能是有意义的。

然而,即便如此,也应检查确切的使用模式,因为完全有可能将Java列表直接传递给Clojure并在没有任何中间seq分配的情况下进行处理。例如,reduce可以ISeq直接有效地进行此类分配。

因此,我将重新审视需要从Java端转移到Clojure的列表需要跨越除ISeq个实例的假设。这并不是说在任何情况下这样的安排都没有意义 - 只是从问题文本中提供的有限细节来看,并不是说在这种情况下这是必要的。

至于如果你最终决定如何实施clojure.lang.ASeq,我同意泰勒伍德关于检查emailVerification(): any { this.afAuth.auth.onAuthStateChanged(function(user) { user.sendEmailVerification(); return true; }); } 的建议。