Enumerable#lazy依赖于你的可枚举提供#each方法.如果您的枚举没有#each方法,则无法使用#lazy.现在Kernel#enum_for,#to_enum提供指定除以下之外的枚举方法的灵活性#each:
Kernel#enum_for(method = :each, *args)
Run Code Online (Sandbox Code Playgroud)
但是#enum_for,朋友总是构建普通(非懒惰)的普查员,从不Enumerator::Lazy.
我看到Enumerator在Ruby 1.9.3中提供了类似的#new形式:
Enumerator#new(obj, method = :each, *args)
Run Code Online (Sandbox Code Playgroud)
不幸的是,在Ruby 2.0中已经完全删除了构造函数.此外,我认为它根本不可用Enumerator::Lazy.所以在我看来,如果我有一个带有方法的类,我想返回一个惰性枚举器,如果该类没有,#each那么我必须定义一些定义的辅助类#each.
例如,我有一Calendar堂课.从一开始就提出列举每一个日期对我来说真的没有意义.一个#each将是无用的.相反,我提供了一个从开始日期(懒惰)枚举的方法:
class Calendar
...
def each_from(first)
if block_given?
loop do
yield first if include?(first)
first += step
end
else
EachFrom.new(self, first).lazy
end
end
end
Run Code Online (Sandbox Code Playgroud)
那个EachFrom班看起来像这样:
class EachFrom
include Enumerable
def initialize(cal, first)
@cal = …Run Code Online (Sandbox Code Playgroud) 我写了一个最小的some-lazy(int)序列类GarbageTest.java,作为一个实验,看看我是否可以在Clojure中以Java的方式处理非常长的懒惰序列.
给定一个naturals()返回惰性无限序列自然数的方法; 一个drop(n,sequence)那滴的第一个方法n的要素sequence,并返回的其余部分sequence; 和一个nth(n,sequence)简单返回的方法:drop(n, lazySeq).head(),我写了两个测试:
static int N = (int)1e6;
// succeeds @ N = (int)1e8 with java -Xmx10m
@Test
public void dropTest() {
assertThat( drop(N, naturals()).head(), is(N+1));
}
// fails with OutOfMemoryError @ N = (int)1e6 with java -Xmx10m
@Test
public void nthTest() {
assertThat( nth(N, naturals()), is(N+1));
}
Run Code Online (Sandbox Code Playgroud)
请注意,dropTest()通过复制主体nthTest()然后在调用上调用IntelliJ的"内联"重构来生成主体nth(N, naturals()).所以在我看来,行为dropTest()应该与行为相同nthTest(). …