重新实现clojure的懒惰seq

时间:2011-05-07 18:35:31

标签: clojure lazy-evaluation

我正在尝试重新实现Clojures lazyseqs作为学习练习,我想弄清楚LazySeq.java中发生了什么,

https://github.com/richhickey/clojure/blob/20090320/src/jvm/clojure/lang/LazySeq.java

这个分支并不假设有分块行为,所以我的想法是假设每次调用fn时都会调用fn,但我无法弄清楚seq调用的作用是什么?更具体地说,按照行,

s = RT.seq(fn.invoke());

1 个答案:

答案 0 :(得分:1)

lazy-seq宏的主体放入函数中。当使用身体产生的序列时,它只是调用该函数来执行身体。您可以 - 或多或少 - 通过以下方式重新实现lazy-seq

(defn simple-lazy-seq*
  [seq-producing-fn]
  (reify
    clojure.lang.Sequential
    clojure.lang.Seqable
    (seq [this] (seq (seq-producing-fn)))))

(defmacro simple-lazy-seq
  [& body]
  `(simple-lazy-seq* (fn [] ~@body)))

来自核心的lazy-seq也提供ISeq接口,但这不是绝对必要的。

编辑:使用纯Java做事。

static Seqable lazy_seq(IFn seq_generating_fn) {
    return new Seqable() {
        ISeq seq() {
            return RT.seq(seq_generating_fn.invoke());
        }
    }
}

YourClass.lazy_seq(new IFn() {
    Object invoke() {
        return thing.returning_the_seq();
    }
});

我不确定我的句法细节是否正确,但它应该是接近的。如你所见,这里有一些限制。例如。 thing必须是final IIRC。但我不是那么流利的Java。