如何实施clojure ISeq inJava?

如何实施clojure ISeq inJava?,java,collections,clojure,Java,Collections,Clojure,我想向Clojure传递Java函数的映射。这些函数使用实现IFn接口的Java匿名类。我还需要实现ISeq接口来传递列表。ISeq接口很简单,但有很多优点。我需要知道ISeq中的每个方法都做了什么,和/或找到实现所有ISeq方法的类的Java代码(我不想关闭结构) 我需要知道ISeq中的每个方法都做了什么 您还应该了解它扩展的接口: public interface Seqable { ISeq seq(); // returns an ISeq instance } public

我想向Clojure传递Java函数的映射。这些函数使用实现IFn接口的Java匿名类。我还需要实现ISeq接口来传递列表。ISeq接口很简单,但有很多优点。我需要知道ISeq中的每个方法都做了什么,和/或找到实现所有ISeq方法的类的Java代码(我不想关闭结构)

我需要知道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的类


除了重新实现ISeq,当然还有一种更容易实现目标的方法。也许看看Clojure的Java实现会给你一些想法。

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

(我不想关闭结构)

情况并非如此。相反,
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发生明显变化

这与传递的
java.util.List
不是同时为
ISeq
seq
的行为形成对比,在这种情况下,确实会分配一个新的seq:

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将被分块,但避免任何包装可能是有意义的

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

因此,我将重新检查一个假设,即需要从Java端传输到Clojure的列表需要作为
ISeq
实例跨越界限。这并不是说在任何情况下这样的安排都是没有意义的——只是从问题文本中提供的有限细节来看,这并不意味着在这种特殊情况下是必要的


至于如何实现
ISeq
,如果您最终决定这样做,我同意Taylor Wood的建议,即检查ASeq类的
clojure.lang.ASeq

文档也缺失。public Obj with meta(IPersistentMap IPersistentMap)方法做什么?@dilvan它获取元数据映射并返回一个附加了该元数据的更新实例。有关更多信息,请参阅和相关函数。My in Java(欢迎评论)。我希望为我的Java类添加支持,避免将数据复制到数组以创建Clojure数据结构。Clojure可以直接处理许多Java收集接口
Iterable
s可以有效地
reduce
(我在回答中提到了这一点),
RandomAccess
实例由
nth
直接支持,Java映射由
get
contains?
&c支持。因此,假设您的Java类实现了预期的Java接口,它们很可能在Clojure中“只工作”,而不需要准备复制到Clojure结构或数组中。事实上,它们很可能会有效地工作。(同样,如果
reduce
/
transduce
您的
Iterable
s&c,您可能不会期望额外的分配。)