car*_*ips 30 ruby lazy-evaluation
如何在Ruby中获取一个惰性数组?
在Haskell中,我可以谈论[1..]
,这是一个无限的列表,根据需要懒洋洋地生成.我也可以做类似的事情iterate (+2) 0
,它应用我给它的任何函数来生成一个惰性列表.在这种情况下,它会给我所有偶数.
我确信我可以在Ruby中做这些事情,但似乎无法弄清楚如何.
car*_*ips 41
使用Ruby 1.9,您可以使用Enumerator类.这是文档中的一个示例:
fib = Enumerator.new { |y|
a = b = 1
loop {
y << a
a, b = b, a + b
}
}
p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Run Code Online (Sandbox Code Playgroud)
此外,这是一个很好的技巧:
Infinity = 1.0/0
range = 5..Infinity
p range.take(10) #=> [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Run Code Online (Sandbox Code Playgroud)
这个只适用于连续值.
gre*_*sen 21
最近Enumerable :: Lazy已添加到ruby trunk.我们将在ruby 2.0中看到它.特别是:
a = data.lazy.map(&:split).map(&:reverse)
Run Code Online (Sandbox Code Playgroud)
不会立即评估.
结果是Enumerable :: Lazy的实例,可以进一步延迟链接.如果你想得到一个实际的结果 - 使用#to_a
,(#take(n)
#take
现在也很懒,使用#to_a
或者#force
等)等等.
如果你想要更多关于这个主题和我的C补丁 - 请参阅我的博客文章Ruby 2.0 Enumerable :: Lazy
懒惰范围(自然数):
Inf = 1.0/0.0
(1..Inf).take(3) #=> [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
懒惰范围(偶数):
(0..Inf).step(2).take(5) #=> [0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)
注意,您还可以Enumerable
使用某些方法进行扩展,以便更方便地使用惰性范围(等等):
module Enumerable
def lazy_select
Enumerator.new do |yielder|
each do |obj|
yielder.yield(obj) if yield(obj)
end
end
end
end
# first 4 even numbers
(1..Inf).lazy_select { |v| v.even? }.take(4)
output:
[2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)
更多信息:http: //banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-ruby/
还有lazy_map和lazy_select的实现Enumerator
,可以在这里找到类:http:
//www.michaelharrison.ws/weblog/? p = 163