在clojure中使用惰性序列

时间:2016-02-19 19:54:51

标签: clojure lazy-sequences

我想知道lazy-seq会返回有限列表或无限列表。有一个例子,

(defn integers [n]
    (cons n (lazy-seq (integers (inc n)))))

当我跑步时

(first integers 10)

(take 5 (integers 10))

结果是10和(10 11 12 13 14) 。但是,当我跑

(integers 10)

该过程无法打印任何内容而无法继续。有没有人可以告诉我为什么和laza-seq的用法。非常感谢你!

4 个答案:

答案 0 :(得分:7)

当你说你正在运行时

(integers 10)

你真正在做的是这样的事情:

user> (integers 10)

换句话说,您正在REPL(read-eval-print-loop)中评估该表单。

“读取”步骤将从字符串"(integers 10)"转换为列表(integers 10)。很简单。

“eval”步骤将在周围的上下文中查找integers,看到它绑定到一个函数,并使用参数10评估该函数:

(cons 10 (lazy-seq (integers (inc 10))))

由于lazy-seq在需要之前未实现,因此只需评估此表单即可生成clojure.lang.Cons元素,其first元素为10且其{ {1}}元素是尚未实现的rest

您可以使用简单的clojure.lang.LazySeq(无无限挂起)来验证这一点:

def

在最后的“打印”步骤中,Clojure基本上尝试将刚评估的表单的结果转换为字符串,然后将该字符串打印到控制台。对于有限序列,这很容易。它只是继续从序列中取出项目,直到没有任何剩余,将每个项目转换为字符串,用空格分隔它们,在末端粘贴一些括号,并且vo:

user> (def my-integers (integers 10))
;=> #'user/my-integers

但是当你定义user> (take 5 (integers 10)) ;=> (10 11 12 13 14) 时,就没有剩下任何项目的点(好吧,至少在你得到整数溢出之前,但是可以通过使用{{}来解决这个问题。 1}}而不仅仅是integers)。因此,Clojure能够很好地读取和评估您的输入,但它无法打印出无限结果的所有项目。

答案 1 :(得分:0)

当你尝试打印无界延迟序列时,它将被完全实现,除非你限制*print-length*

答案 2 :(得分:0)

#define VALUEA "A" #define VALUEB "B" #define CHOOSE VALUEA #define MY_MACRO CHOOSE // CHOOSE -> VALUEA // MY_MACRO -> VALUEA #define TEMP MY_MACRO // save #undef MY_MACRO #define CHOOSE VALUEB #define MY_MACRO TEMP // restore // CHOOSE -> VALUEB // MY_MACRO -> VALUEA 从不构造列表,有限或无限。它构造了一个lazy-seq对象。这是一个名义序列,它包含一个无参数的函数(通常称为thunk),在调用时计算为实际序列;但它必须被调用,这就是机制的目的:延迟评估实际的序列。

因此,您可以将评估的 clojure.lang.LazySeq对象传递给无限序列,前提是您从未实现它们。您在REPL的评估会调用实现,这是一个无休止的过程。

答案 3 :(得分:-1)

它没有返回任何内容,因为你的整数函数会产生无限循环。

(defn integers [n]
  (do (prn n)
      (cons n (lazy-seq (integers (inc n))))))

使用(integers 10)进行调用,您将看到它永远计数。