Реализовывать ленивый seq clojure - PullRequest
3 голосов
/ 07 мая 2011

Я пытаюсь внедрить Clojures lazyseqs как учебное упражнение, я пытаюсь выяснить, что происходит в LazySeq.java,

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

эта ветвь делаетЯ не думаю, что у него будет чанкинг, поэтому я думаю, что каждый раз вызывается fn, но я не могу понять, что делает вызов seq?более конкретно следующая строка,

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

1 Ответ

1 голос
/ 07 мая 2011

Тело макроса 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.

...