枚举器作为 Ruby 中的无限生成器 [英] Enumerator as an infinite generator in Ruby

查看:40
本文介绍了枚举器作为 Ruby 中的无限生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读一篇解释如何将枚举器用作生成器的资源,例如:

I'm reading one resource explaining how Enumerators can be used as generators, which as an example like:

triangular_numbers = Enumerator.new do |yielder|
  number = 0
  count = 1
  loop do
    number += count
    count += 1
    yielder.yield number
  end
end

print triangular_numbers.next, " " 
print triangular_numbers.next, " " 
print triangular_numbers.next, " " 

我不明白 yelder 在这里的目的,它需要什么价值,以及这段代码如何与程序的其余代码并行执行.

I don't understand the purpose of yielder here, what value it takes, and how this code is executing in parallel with the rest of the program's code.

执行从顶部开始,可能会在块产生"一个值给我的代码时暂停.

The execution starts at the top, and pauses probably when the block "yields" a value to my code.

有人可以解释一下在编译器眼中所有这些是如何执行的吗?

Can someone please explain how all this executes in the compiler's eyes?

推荐答案

我想我发现了一些你可能会感兴趣的东西.

I think I've found something that you may find interesting.

本文:Pat Shaughnessy 撰写的Ruby 2.0 Works Hard So You Can Be Lazy" 解释了 Eager 和 Lazy 评估背后的思想,并解释了它与框架类"的关系.比如 Enumerale、Generator 或 Yielder.它主要集中在解释如何实现 LazyEvaluation,但仍然非常详细.

This article: 'Ruby 2.0 Works Hard So You Can Be Lazy' by Pat Shaughnessy explains the ideas behind Eager and Lazy evaluation, and also explains how that relates to the "framework classes" like Enumerale, Generator or Yielder. It is mostly focused on explaining how to achieve LazyEvaluation, but still, it's quite detailed.

Ruby 2.0 使用名为 Enumerator::Lazy 的对象实现惰性求值.它的特别之处在于它同时扮演了两个角色!它是一个枚举器,还包含一系列 Enumerable 方法.它调用每个以从枚举源获取数据,并为枚举的其余部分生成数据.由于 Enumerator::Lazy 扮演这两个角色,您可以将它们链接在一起以生成单个枚举.

这是 Ruby 中惰性求值的关键.来自数据源的每个值都被交给我的块,然后结果立即沿着枚举链向下传递.这个枚举不是急切的—— Enumerator::Lazy#collect 方法不会将值收集到数组中.取而代之的是,通过重复的产量,每个值沿着 Enumerator::Lazy 对象链一次传递一个.如果我将一系列对 collect 或其他 Enumerator::Lazy 方法的调用链接在一起,则每个值都将沿着链从一个块传递到下一个块,一次一个

Enumerable#first 都通过在惰性枚举器上调用 each 来开始迭代,并通过在有足够的值时引发异常来结束迭代.

归根结底,这是惰性求值背后的关键思想:计算链末端的函数或方法开始执行过程,程序的流程通过函数调用链向后工作,直到它只获取数据它需要的输入.Ruby 使用 Enumerator::Lazy 对象链来实现这一点.

Ruby 2.0 implements lazy evaluation using an object called Enumerator::Lazy. What makes this special is that it plays both roles! It is an enumerator, and also contains a series of Enumerable methods. It calls each to obtain data from an enumeration source, and it yields data to the rest of an enumeration. Since Enumerator::Lazy plays both roles, you can chain them up together to produce a single enumeration.

This is the key to lazy evaluation in Ruby. Each value from the data source is yielded to my block, and then the result is immediately passed along down the enumeration chain. This enumeration is not eager – the Enumerator::Lazy#collect method does not collect the values into an array. Instead, each value is passed one at a time along the chain of Enumerator::Lazy objects, via repeated yields. If I had chained together a series of calls to collect or other Enumerator::Lazy methods, each value would be passed along the chain from one of my blocks to the next, one at a time

Enumerable#first both starts the iteration by calling each on the lazy enumerators, and ends the iteration by raising an exception when it has enough values.

At the end of the day, this is the key idea behind lazy evaluation: the function or method at the end of a calculation chain starts the execution process, and the program’s flow works backwards through the chain of function calls until it obtains just the data inputs it needs. Ruby achieves this using a chain of Enumerator::Lazy objects.

这篇关于枚举器作为 Ruby 中的无限生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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