如何在Clojure中实现延迟序列? [英] How Are Lazy Sequences Implemented in Clojure?

查看:141
本文介绍了如何在Clojure中实现延迟序列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢Clojure。有一件事让我困扰我的语言是,我不知道如何实现延迟序列或它们如何工作。

I like Clojure. One thing that bothers me about the language is that I don't know how lazy sequences are implemented, or how they work.

我知道惰性序列只评估项目在要求的顺序。

I know that lazy sequences only evaluate the items in the sequence that are asked for. How does it do this?


  • 什么使延迟序列如此有效,以至于它们不会消耗太多的
    堆栈?

  • 如何才能在延迟序列中包装递归调用,并且没有
    更长的时间为大型计算获得堆栈溢出?


  • 在什么情况下,延迟序列效率最高?
  • >
  • What makes lazy sequences so efficient that they don't consume much stack?
  • How come you can wrap recursive calls in a lazy sequence and no longer get a stack over flow for large computations?
  • What resources do lazy sequences consume to do what it does?
  • In what scenarios are lazy sequences inefficient?
  • In what scenarios are lazy sequences most efficient?

推荐答案

让我们这样做。

I know that lazy sequences only evaluate the items in the sequence that are asked for, how does it do this?

延迟序列(此后称为LS) ,因为我是一个LP,或者Lazy Person)都是由部分组成的。 头部,或者部分(s,因为真正的32个元素一次被评估,从Clojure 1.1,和我认为1.2)的序列已经评估,后面是一些称为 thunk ,这基本上是一个信息块(认为它是你的函数的其余部分创建序列,未评估)等待被调用。当它被调用时,thunk评估,但是很多被要求它,并创建一个新的thunk,根据需要上下文(已经调用了多少,所以它可以从之前的地方恢复)。

Lazy sequences (henceforth LS, because I am a LP, or Lazy Person) are composed of parts. The head, or the part(s, as really 32 elements are evaluated at a time, as of Clojure 1.1, and I think 1.2) of the sequence that have been evaluated, is followed by something called a thunk, which is basically a chunk of information (think of it as the rest of the your function that creates the sequence, unevaluated) waiting to be called. When it is called, the thunk evaluates however much is asked of it, and a new thunk is created, with context as necessary (how much has been called already, so it can resume from where it was before).

所以你(取10(整数)) - 假设 是一个懒惰的整数序列。这意味着你迫使thunks评估10次(虽然在内部这可能有一点差异取决于优化。

So you (take 10 (whole-numbers)) – assume whole-numbers is a lazy sequence of whole numbers. That means you're forcing evaluation of thunks 10 times (though internally this may be a little difference depending on optimizations.

使惰性序列如此高效他们不消耗太多堆栈?

一旦你阅读了上面的答案(我希望),这变得更清楚:除非你特别要求某事,否则

This becomes clearer once you read the previous answer (I hope): unless you call for something in particular, nothing is evaluated. When you call for something, each element of the sequence can be evaluated individually, then discarded.

如果序列不是惰性的,通常它会保持它的头,它消耗堆空间,如果它是惰性的,它是计算,然后丢弃,因为它不需要后续的计算。

If the sequence is not lazy, oftentimes it is holding onto its head, which consumes heap space. If it is lazy, it is computed, then discarded, as it is not required for subsequent computations.

请参阅上一个答案并考虑: lazy-seq 宏(从文档)将

See the previous answer and consider: the lazy-seq macro (from the documentation) will

will invoke the body only the first time seq
is called, and will cache the result and return it on all subsequent
seq calls.

检查过滤器 LS使用递归:

(defn filter
  "Returns a lazy sequence of the items in coll for which
  (pred item) returns true. pred must be free of side-effects."
  [pred coll]
  (let [step (fn [p c]
                 (when-let [s (seq c)]
                   (if (p (first s))
                     (cons (first s) (filter p (rest s)))
                     (recur p (rest s)))))]
    (lazy-seq (step pred coll))))



惰性序列消耗了什么资源来做它做什么?

我不太确定你在这里要求什么。 LS需要内存和CPU周期。他们只是不保持撞击堆栈,并填充获得序列元素所需的计算结果。

I'm not quite sure what you're asking here. LSs require memory and CPU cycles. They just don't keep banging the stack, and filling it up with results of the computations required to get the sequence elements.

在什么情况下延迟序列效率低下?

使用快速计算并且不会被使用的小seq,使得它是低效的,因为它需要另外两个字符来创建。

When you're using small seqs that are fast to compute and won't be used much, making it an LS is inefficient because it requires another couple chars to create.

在所有严重的情况下,除非你想要非常做某些事情,LS是要走的路。

In all seriousness, unless you're trying to make something extremely performant, LSs are the way to go.

在什么情况下延迟序列效率最高?

're处理seqs是巨大的,你只使用它们的位和块,这是当你从使用它们最大的好处。

When you're dealing with seqs that are huge and you're only using bits and pieces of them, that is when you get the most benefit from using them.

真的,在方便,易于理解(一旦你得到了它们的悬念)和推理方面,使用LSs比非LS更好你的代码和速度。

Really, it's pretty much always better to use LSs over non-LSs, in terms of convenience, ease of understanding (once you get the hang of them) and reasoning about your code, and speed.

这篇关于如何在Clojure中实现延迟序列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆