【问题标题】:Extracting the contents of a Clojure vector as a LazySeq将 Clojure 向量的内容提取为 LazySeq
【发布时间】:2014-02-03 15:56:00
【问题描述】:

我使用 Clojure 的 Java API,我有一个通过代码创建的持久向量:

 IPersistentVector vec = PersistentVector.create();

然后用值填充。

我需要将此向量的内容提取为LazySeq。我知道向量的方法seq() 返回一个ISeq。有没有办法将此ISeq 转换为LazySeq

谢谢,

克里斯

【问题讨论】:

  • 您能否详细介绍一下为什么您需要一个 LazySeq 实例? Clojure 的序列库旨在让您无需了解底层数据结构。

标签: clojure lazy-sequences


【解决方案1】:

ISeq 是 seqs 的接口,所以LazySeq 也实现了ISeqseq 函数类型提示其返回为 ISeq

在向量上调用seq 将返回PersistentVector$ChunkedSeq,这是一种不同的惰性序列。它的实现被分块以逐个元素地摊销生产它的成本(我认为它一次评估 8 个元素 iirc)。

如果你真的特别想要LazySeq,你可以这样做

(lazy-cat [1 2 3])

但这只会对强制逐元素评估和消除分块行为有用。

在 Java 中,这将是:

// once
Var lazyCat = RT.var("clojure.core", "lazy-cat");

// at use
IPersistentVector vector = ...
ISeq lv = (ISeq) lazyCat.invoke(vector);

请注意,实际上将结果转换为LazySeq 会给我带来麻烦,所以我在这里还是使用了接口ISeq没有保证具体类LazySeq 是您在未来任何时候实际收到的。鉴于此,您也可以直接调用 seq:

// once
Var seq = RT.var("clojure.core", "seq");

// at use
IPersistentVector vector = ...
ISeq lv = (ISeq) seq.invoke(vector);

一般来说,最好总是通过从运行时获得的 Var 调用 Clojure 类,并且只转换为接口,而不是具体类型。这大大降低了在不同版本之间发生问题的可能性。

【讨论】:

  • lazy-cat 是一个宏,所以这行不通。但是,正如你所说,无论如何,整件事都是个坏主意,所以这不是什么损失。
【解决方案2】:

我完全想不出这样做的好理由和几个不好的理由,但这是较低的水平。

import clojure.lang.*;

public class Foo {
    public static IFn thunk(final Object x){
           return new AFn(){
               public Object invoke() { return x; } 
           }; 
    }

     public static void main(String[] args) throws Exception {
         PersistentVector vec;
         LazySeq lazySeq;

         vec = PersistentVector.create(1, 2, 3);
         System.out.println(vec);

         lazySeq = new LazySeq(thunk(vec));
         System.out.println(lazySeq);
         System.out.println(RT.printString(lazySeq));
     }
}

输出,例如

[1 2 3]
clojure.lang.LazySeq@7861
(1 2 3)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    相关资源
    最近更新 更多