Skip to content

Commit e20d922

Browse files
sampokuokkaneneregon
authored andcommitted
Add specs for #each passing source yields by block arity (Enumerator and Lazy)
Unlike the Enumerable collection methods, which pack yielded source values via rb_enum_values_pack() (0 args -> nil, 1 arg -> the value, N args -> Array), #each passes them to the block by ordinary block arity (rb_yield_values2() in CRuby): a single-argument block receives the first value, a multi-argument block destructures, and a splat block gathers them.
1 parent 54e4a18 commit e20d922

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

core/enumerator/each_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
require_relative '../../spec_helper'
2+
require_relative 'shared/each'
23

34
describe "Enumerator#each" do
5+
describe "passing source-yielded arguments to the block" do
6+
before :each do
7+
@object = -> e { e }
8+
end
9+
it_behaves_like :enum_each, nil
10+
end
11+
12+
describe "passing source-yielded arguments to the block (lazy)" do
13+
before :each do
14+
@object = -> e { e.lazy }
15+
end
16+
it_behaves_like :enum_each, nil
17+
end
18+
419
before :each do
520
object_each_with_arguments = Object.new
621
def object_each_with_arguments.each_with_arguments(arg, *args)

core/enumerator/shared/each.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# #each passes source-yielded values to the block by ordinary block arity
2+
# (rb_yield_values2 semantics in CRuby), unlike the Enumerable collection methods
3+
# which pack them via rb_enum_values_pack() (see enumerable/shared/value_packing.rb).
4+
describe :enum_each, shared: true do
5+
# @object must be set to a Proc that wraps an Enumerator into the receiver
6+
# under test (e.g. -> e { e } for Enumerator#each, -> e { e.lazy } for Lazy#each).
7+
describe "with a source that yields multiple values" do
8+
before :each do
9+
@enum = @object.call(Enumerator.new { |y| y.yield 1, 2; y.yield 3, 4 })
10+
end
11+
12+
it "yields the first value to a single-argument block" do
13+
collected = []
14+
@enum.each { |x| collected << x }
15+
collected.should == [1, 3]
16+
end
17+
18+
it "yields each value to a multi-argument block" do
19+
collected = []
20+
@enum.each { |x, y| collected << [x, y] }
21+
collected.should == [[1, 2], [3, 4]]
22+
end
23+
24+
it "gathers the values for a splat block" do
25+
collected = []
26+
@enum.each { |*args| collected << args }
27+
collected.should == [[1, 2], [3, 4]]
28+
end
29+
end
30+
31+
describe "with a source that yields a single value" do
32+
it "yields the value to a single-argument block" do
33+
collected = []
34+
@object.call(Enumerator.new { |y| y.yield 7; y.yield 8 }).each { |x| collected << x }
35+
collected.should == [7, 8]
36+
end
37+
end
38+
39+
describe "with a source that yields no value" do
40+
it "yields nil to a single-argument block" do
41+
collected = []
42+
@object.call(Enumerator.new { |y| y.yield; y.yield }).each { |x| collected << x }
43+
collected.should == [nil, nil]
44+
end
45+
end
46+
end

0 commit comments

Comments
 (0)