如何实施clojure ISeq inJava?
我想向Clojure传递Java函数的映射。这些函数使用实现IFn接口的Java匿名类。我还需要实现ISeq接口来传递列表。ISeq接口很简单,但有很多优点。我需要知道ISeq中的每个方法都做了什么,和/或找到实现所有ISeq方法的类的Java代码(我不想关闭结构) 我需要知道ISeq中的每个方法都做了什么 您还应该了解它扩展的接口:如何实施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
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,您可能不会期望额外的分配。)