gpt4 book ai didi

Ruby 等同于 C#'s ' yield' 关键字,或者,在不预分配内存的情况下创建序列

转载 作者:数据小太阳 更新时间:2023-10-29 06:56:18 26 4
gpt4 key购买 nike

在 C# 中,您可以这样做:

public IEnumerable<T> GetItems<T>()
{
for (int i=0; i<10000000; i++) {
yield return i;
}
}

这将返回一个包含 1000 万个整数的可枚举序列,而无需在该长度的内存中分配一个集合。

有没有一种方法可以在 Ruby 中做同样的事情?我要处理的具体示例是将矩形数组展平为要枚举的值序列。返回值不必是 ArraySet ,而是某种只能按顺序而不是索引迭代/枚举的序列。因此,整个序列不需要同时分配到内存中。在 .NET 中,这是 IEnumerableIEnumerable<T> .

对 Ruby 世界中此处使用的术语的任何澄清都会有所帮助,因为我更熟悉 .NET 术语。

编辑

也许我最初的问题还不够清楚——我认为 yield在 C# 中具有非常不同的含义,而 Ruby 是造成混淆的原因。

我不想要一个需要我的方法使用 block 的解决方案。我想要一个具有实际返回值的解决方案。返回值允许方便地处理序列(过滤、投影、连接、压缩等)。

这是我如何使用 get_items 的一个简单示例:

things = obj.get_items.select { |i| !i.thing.nil? }.map { |i| i.thing }

在 C# 中,任何返回 IEnumerable 的方法使用 yield return导致编译器在幕后生成一个有限状态机来满足这种行为。我怀疑使用 Ruby 的延续可以实现类似的东西,但我还没有看到一个例子,而且我自己也不太清楚如何做到这一点。

我确实有可能使用 Enumerable 为达到这个。一个简单的解决方案对我们来说是 Array (其中包括模块 Enumerable ),但我不想在内存中创建一个包含 N 项的中间集合,因为可以懒惰地提供它们并完全避免任何内存峰值。

如果这仍然没有意义,请考虑上面的代码示例。 get_items返回一个枚举,select叫做。传递给 select 的内容是一个知道如何在需要时提供序列中的下一项的实例。重要的是,尚未计算整个项目集合。仅当 select需要一个项目,它会要求它,以及 get_items 中的潜在代码将开始行动并提供它。这种懒惰沿着链条进行,这样select仅在 map 时从序列中提取下一项要求它。因此,一次可以对一个数据项执行一长串操作。事实上,以这种方式构建的代码甚至可以处理无限值序列而不会出现任何类型的内存错误。

所以,这种懒惰很容易在 C# 中编码,而我不知道如何在 Ruby 中做到这一点。

我希望这更清楚(以后我会尽量避免在凌晨 3 点写问题。)

最佳答案

Enumerator 支持从 Ruby 1.9 开始(并向后移植到 1.8.7)。参见 Generator: Ruby .

陈词滥调的例子:

fib = Enumerator.new do |y|
y.yield i = 0
y.yield j = 1
while true
k = i + j
y.yield k
i = j
j = k
end
end

100.times { puts fib.next() }

关于Ruby 等同于 C#'s ' yield' 关键字,或者,在不预分配内存的情况下创建序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2282615/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com