2015-12-16 00:07:31 -05:00
|
|
|
# frozen_string_literal: false
|
2012-03-08 20:13:59 -05:00
|
|
|
require 'test/unit'
|
|
|
|
|
|
|
|
class TestLazyEnumerator < Test::Unit::TestCase
|
|
|
|
class Step
|
|
|
|
include Enumerable
|
|
|
|
attr_reader :current, :args
|
|
|
|
|
|
|
|
def initialize(enum)
|
|
|
|
@enum = enum
|
|
|
|
@current = nil
|
|
|
|
@args = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def each(*args)
|
|
|
|
@args = args
|
2017-06-10 06:26:32 -04:00
|
|
|
@enum.each do |v|
|
|
|
|
@current = v
|
|
|
|
if v.is_a? Enumerable
|
2019-06-01 08:20:21 -04:00
|
|
|
yield(*v)
|
2017-06-10 06:26:32 -04:00
|
|
|
else
|
2019-06-01 08:20:21 -04:00
|
|
|
yield(v)
|
2017-06-10 06:26:32 -04:00
|
|
|
end
|
|
|
|
end
|
2012-03-08 20:13:59 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_initialize
|
|
|
|
assert_equal([1, 2, 3], [1, 2, 3].lazy.to_a)
|
2013-02-04 22:49:41 -05:00
|
|
|
assert_equal([1, 2, 3], Enumerator::Lazy.new([1, 2, 3]){|y, v| y << v}.to_a)
|
|
|
|
assert_raise(ArgumentError) { Enumerator::Lazy.new([1, 2, 3]) }
|
2013-07-29 08:20:19 -04:00
|
|
|
|
|
|
|
a = [1, 2, 3].lazy
|
|
|
|
a.freeze
|
2017-12-11 19:46:34 -05:00
|
|
|
assert_raise(FrozenError) {
|
2013-07-29 08:20:19 -04:00
|
|
|
a.__send__ :initialize, [4, 5], &->(y, *v) { y << yield(*v) }
|
|
|
|
}
|
2012-03-08 20:13:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_each_args
|
|
|
|
a = Step.new(1..3)
|
|
|
|
assert_equal(1, a.lazy.each(4).first)
|
|
|
|
assert_equal([4], a.args)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_each_line
|
|
|
|
name = lineno = nil
|
|
|
|
File.open(__FILE__) do |f|
|
|
|
|
f.each("").map do |paragraph|
|
|
|
|
paragraph[/\A\s*(.*)/, 1]
|
|
|
|
end.find do |line|
|
|
|
|
if name = line[/^class\s+(\S+)/, 1]
|
|
|
|
lineno = f.lineno
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assert_equal(self.class.name, name)
|
|
|
|
assert_operator(lineno, :>, 2)
|
|
|
|
|
|
|
|
name = lineno = nil
|
|
|
|
File.open(__FILE__) do |f|
|
|
|
|
f.lazy.each("").map do |paragraph|
|
|
|
|
paragraph[/\A\s*(.*)/, 1]
|
|
|
|
end.find do |line|
|
|
|
|
if name = line[/^class\s+(\S+)/, 1]
|
|
|
|
lineno = f.lineno
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assert_equal(self.class.name, name)
|
|
|
|
assert_equal(2, lineno)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_select
|
|
|
|
a = Step.new(1..6)
|
|
|
|
assert_equal(4, a.select {|x| x > 3}.first)
|
|
|
|
assert_equal(6, a.current)
|
|
|
|
assert_equal(4, a.lazy.select {|x| x > 3}.first)
|
|
|
|
assert_equal(4, a.current)
|
|
|
|
|
|
|
|
a = Step.new(['word', nil, 1])
|
|
|
|
assert_raise(TypeError) {a.select {|x| "x"+x}.first}
|
|
|
|
assert_equal(nil, a.current)
|
|
|
|
assert_equal("word", a.lazy.select {|x| "x"+x}.first)
|
|
|
|
assert_equal("word", a.current)
|
|
|
|
end
|
|
|
|
|
2012-03-15 10:20:27 -04:00
|
|
|
def test_select_multiple_values
|
|
|
|
e = Enumerator.new { |yielder|
|
|
|
|
for i in 1..5
|
|
|
|
yielder.yield(i, i.to_s)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
assert_equal([[2, "2"], [4, "4"]],
|
|
|
|
e.select {|x| x[0] % 2 == 0})
|
|
|
|
assert_equal([[2, "2"], [4, "4"]],
|
|
|
|
e.lazy.select {|x| x[0] % 2 == 0}.force)
|
|
|
|
end
|
|
|
|
|
2012-03-08 20:13:59 -05:00
|
|
|
def test_map
|
|
|
|
a = Step.new(1..3)
|
|
|
|
assert_equal(2, a.map {|x| x * 2}.first)
|
|
|
|
assert_equal(3, a.current)
|
|
|
|
assert_equal(2, a.lazy.map {|x| x * 2}.first)
|
|
|
|
assert_equal(1, a.current)
|
|
|
|
end
|
|
|
|
|
2017-06-10 06:26:32 -04:00
|
|
|
def test_map_packed_nested
|
|
|
|
bug = '[ruby-core:81638] [Bug#13648]'
|
|
|
|
|
|
|
|
a = Step.new([[1, 2]])
|
|
|
|
expected = [[[1, 2]]]
|
|
|
|
assert_equal(expected, a.map {|*args| args}.map {|*args| args}.to_a)
|
|
|
|
assert_equal(expected, a.lazy.map {|*args| args}.map {|*args| args}.to_a, bug)
|
|
|
|
end
|
|
|
|
|
2012-03-09 00:34:41 -05:00
|
|
|
def test_flat_map
|
|
|
|
a = Step.new(1..3)
|
|
|
|
assert_equal(2, a.flat_map {|x| [x * 2]}.first)
|
|
|
|
assert_equal(3, a.current)
|
|
|
|
assert_equal(2, a.lazy.flat_map {|x| [x * 2]}.first)
|
|
|
|
assert_equal(1, a.current)
|
|
|
|
end
|
|
|
|
|
2012-03-13 19:16:37 -04:00
|
|
|
def test_flat_map_nested
|
|
|
|
a = Step.new(1..3)
|
|
|
|
assert_equal([1, "a"],
|
|
|
|
a.flat_map {|x| ("a".."c").map {|y| [x, y]}}.first)
|
|
|
|
assert_equal(3, a.current)
|
|
|
|
assert_equal([1, "a"],
|
|
|
|
a.lazy.flat_map {|x| ("a".."c").lazy.map {|y| [x, y]}}.first)
|
|
|
|
assert_equal(1, a.current)
|
|
|
|
end
|
|
|
|
|
2012-03-19 04:22:29 -04:00
|
|
|
def test_flat_map_to_ary
|
|
|
|
to_ary = Class.new {
|
|
|
|
def initialize(value)
|
|
|
|
@value = value
|
|
|
|
end
|
|
|
|
|
|
|
|
def to_ary
|
|
|
|
[:to_ary, @value]
|
|
|
|
end
|
|
|
|
}
|
|
|
|
assert_equal([:to_ary, 1, :to_ary, 2, :to_ary, 3],
|
|
|
|
[1, 2, 3].flat_map {|x| to_ary.new(x)})
|
|
|
|
assert_equal([:to_ary, 1, :to_ary, 2, :to_ary, 3],
|
|
|
|
[1, 2, 3].lazy.flat_map {|x| to_ary.new(x)}.force)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_flat_map_non_array
|
|
|
|
assert_equal(["1", "2", "3"], [1, 2, 3].flat_map {|x| x.to_s})
|
|
|
|
assert_equal(["1", "2", "3"], [1, 2, 3].lazy.flat_map {|x| x.to_s}.force)
|
|
|
|
end
|
|
|
|
|
2013-01-14 03:36:15 -05:00
|
|
|
def test_flat_map_hash
|
|
|
|
assert_equal([{?a=>97}, {?b=>98}, {?c=>99}], [?a, ?b, ?c].flat_map {|x| {x=>x.ord}})
|
|
|
|
assert_equal([{?a=>97}, {?b=>98}, {?c=>99}], [?a, ?b, ?c].lazy.flat_map {|x| {x=>x.ord}}.force)
|
|
|
|
end
|
|
|
|
|
2012-03-08 20:13:59 -05:00
|
|
|
def test_reject
|
|
|
|
a = Step.new(1..6)
|
|
|
|
assert_equal(4, a.reject {|x| x < 4}.first)
|
|
|
|
assert_equal(6, a.current)
|
|
|
|
assert_equal(4, a.lazy.reject {|x| x < 4}.first)
|
|
|
|
assert_equal(4, a.current)
|
|
|
|
|
|
|
|
a = Step.new(['word', nil, 1])
|
|
|
|
assert_equal(nil, a.reject {|x| x}.first)
|
|
|
|
assert_equal(1, a.current)
|
|
|
|
assert_equal(nil, a.lazy.reject {|x| x}.first)
|
|
|
|
assert_equal(nil, a.current)
|
|
|
|
end
|
|
|
|
|
2012-03-15 10:20:27 -04:00
|
|
|
def test_reject_multiple_values
|
|
|
|
e = Enumerator.new { |yielder|
|
|
|
|
for i in 1..5
|
|
|
|
yielder.yield(i, i.to_s)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
assert_equal([[2, "2"], [4, "4"]],
|
|
|
|
e.reject {|x| x[0] % 2 != 0})
|
|
|
|
assert_equal([[2, "2"], [4, "4"]],
|
|
|
|
e.lazy.reject {|x| x[0] % 2 != 0}.force)
|
|
|
|
end
|
|
|
|
|
2012-03-08 20:13:59 -05:00
|
|
|
def test_grep
|
|
|
|
a = Step.new('a'..'f')
|
|
|
|
assert_equal('c', a.grep(/c/).first)
|
|
|
|
assert_equal('f', a.current)
|
|
|
|
assert_equal('c', a.lazy.grep(/c/).first)
|
|
|
|
assert_equal('c', a.current)
|
2012-03-13 21:44:37 -04:00
|
|
|
assert_equal(%w[a e], a.grep(proc {|x| /[aeiou]/ =~ x}))
|
|
|
|
assert_equal(%w[a e], a.lazy.grep(proc {|x| /[aeiou]/ =~ x}).to_a)
|
2012-03-08 20:13:59 -05:00
|
|
|
end
|
2012-03-13 19:08:15 -04:00
|
|
|
|
2012-03-15 10:20:27 -04:00
|
|
|
def test_grep_with_block
|
|
|
|
a = Step.new('a'..'f')
|
|
|
|
assert_equal('C', a.grep(/c/) {|i| i.upcase}.first)
|
|
|
|
assert_equal('C', a.lazy.grep(/c/) {|i| i.upcase}.first)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_grep_multiple_values
|
|
|
|
e = Enumerator.new { |yielder|
|
|
|
|
3.times { |i|
|
|
|
|
yielder.yield(i, i.to_s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert_equal([[2, "2"]], e.grep(proc {|x| x == [2, "2"]}))
|
|
|
|
assert_equal([[2, "2"]], e.lazy.grep(proc {|x| x == [2, "2"]}).force)
|
|
|
|
assert_equal(["22"],
|
|
|
|
e.lazy.grep(proc {|x| x == [2, "2"]}, &:join).force)
|
|
|
|
end
|
|
|
|
|
2015-12-08 02:23:43 -05:00
|
|
|
def test_grep_v
|
|
|
|
a = Step.new('a'..'f')
|
|
|
|
assert_equal('b', a.grep_v(/a/).first)
|
|
|
|
assert_equal('f', a.current)
|
|
|
|
assert_equal('a', a.lazy.grep_v(/c/).first)
|
|
|
|
assert_equal('a', a.current)
|
|
|
|
assert_equal(%w[b c d f], a.grep_v(proc {|x| /[aeiou]/ =~ x}))
|
|
|
|
assert_equal(%w[b c d f], a.lazy.grep_v(proc {|x| /[aeiou]/ =~ x}).to_a)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_grep_v_with_block
|
|
|
|
a = Step.new('a'..'f')
|
|
|
|
assert_equal('B', a.grep_v(/a/) {|i| i.upcase}.first)
|
|
|
|
assert_equal('B', a.lazy.grep_v(/a/) {|i| i.upcase}.first)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_grep_v_multiple_values
|
|
|
|
e = Enumerator.new { |yielder|
|
|
|
|
3.times { |i|
|
|
|
|
yielder.yield(i, i.to_s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert_equal([[0, "0"], [1, "1"]], e.grep_v(proc {|x| x == [2, "2"]}))
|
|
|
|
assert_equal([[0, "0"], [1, "1"]], e.lazy.grep_v(proc {|x| x == [2, "2"]}).force)
|
|
|
|
assert_equal(["00", "11"],
|
|
|
|
e.lazy.grep_v(proc {|x| x == [2, "2"]}, &:join).force)
|
|
|
|
end
|
|
|
|
|
2012-03-13 19:08:15 -04:00
|
|
|
def test_zip
|
|
|
|
a = Step.new(1..3)
|
|
|
|
assert_equal([1, "a"], a.zip("a".."c").first)
|
|
|
|
assert_equal(3, a.current)
|
|
|
|
assert_equal([1, "a"], a.lazy.zip("a".."c").first)
|
|
|
|
assert_equal(1, a.current)
|
|
|
|
end
|
2012-03-13 21:35:09 -04:00
|
|
|
|
2012-03-15 06:14:22 -04:00
|
|
|
def test_zip_short_arg
|
|
|
|
a = Step.new(1..5)
|
|
|
|
assert_equal([5, nil], a.zip("a".."c").last)
|
|
|
|
assert_equal([5, nil], a.lazy.zip("a".."c").force.last)
|
|
|
|
end
|
|
|
|
|
2012-03-13 19:08:15 -04:00
|
|
|
def test_zip_without_arg
|
|
|
|
a = Step.new(1..3)
|
|
|
|
assert_equal([1], a.zip.first)
|
|
|
|
assert_equal(3, a.current)
|
|
|
|
assert_equal([1], a.lazy.zip.first)
|
|
|
|
assert_equal(1, a.current)
|
|
|
|
end
|
|
|
|
|
2013-01-24 02:50:33 -05:00
|
|
|
def test_zip_bad_arg
|
|
|
|
a = Step.new(1..3)
|
|
|
|
assert_raise(TypeError){ a.lazy.zip(42) }
|
|
|
|
end
|
|
|
|
|
2012-03-13 19:08:15 -04:00
|
|
|
def test_zip_with_block
|
2012-03-15 05:25:03 -04:00
|
|
|
# zip should be eager when a block is given
|
2012-03-13 19:08:15 -04:00
|
|
|
a = Step.new(1..3)
|
2012-03-15 05:25:03 -04:00
|
|
|
ary = []
|
|
|
|
assert_equal(nil, a.lazy.zip("a".."c") {|x, y| ary << [x, y]})
|
|
|
|
assert_equal(a.zip("a".."c"), ary)
|
|
|
|
assert_equal(3, a.current)
|
2012-03-13 19:08:15 -04:00
|
|
|
end
|
2012-03-14 06:29:25 -04:00
|
|
|
|
|
|
|
def test_take
|
2012-03-14 09:04:18 -04:00
|
|
|
a = Step.new(1..10)
|
|
|
|
assert_equal(1, a.take(5).first)
|
|
|
|
assert_equal(5, a.current)
|
|
|
|
assert_equal(1, a.lazy.take(5).first)
|
|
|
|
assert_equal(1, a.current)
|
2012-03-15 22:22:20 -04:00
|
|
|
assert_equal((1..5).to_a, a.lazy.take(5).force)
|
|
|
|
assert_equal(5, a.current)
|
|
|
|
a = Step.new(1..10)
|
|
|
|
assert_equal([], a.lazy.take(0).force)
|
|
|
|
assert_equal(nil, a.current)
|
2012-03-14 09:04:18 -04:00
|
|
|
end
|
|
|
|
|
2015-12-31 18:53:04 -05:00
|
|
|
def test_take_bad_arg
|
|
|
|
a = Step.new(1..10)
|
|
|
|
assert_raise(ArgumentError) { a.lazy.take(-1) }
|
|
|
|
end
|
|
|
|
|
2012-05-13 11:24:40 -04:00
|
|
|
def test_take_recycle
|
|
|
|
bug6428 = '[ruby-dev:45634]'
|
|
|
|
a = Step.new(1..10)
|
|
|
|
take5 = a.lazy.take(5)
|
|
|
|
assert_equal((1..5).to_a, take5.force, bug6428)
|
|
|
|
assert_equal((1..5).to_a, take5.force, bug6428)
|
|
|
|
end
|
|
|
|
|
2013-01-24 01:22:34 -05:00
|
|
|
def test_take_nested
|
|
|
|
bug7696 = '[ruby-core:51470]'
|
|
|
|
a = Step.new(1..10)
|
|
|
|
take5 = a.lazy.take(5)
|
|
|
|
assert_equal([*(1..5)]*5, take5.flat_map{take5}.force, bug7696)
|
|
|
|
end
|
|
|
|
|
2013-01-24 01:23:07 -05:00
|
|
|
def test_drop_while_nested
|
|
|
|
bug7696 = '[ruby-core:51470]'
|
|
|
|
a = Step.new(1..10)
|
|
|
|
drop5 = a.lazy.drop_while{|x| x < 6}
|
|
|
|
assert_equal([*(6..10)]*5, drop5.flat_map{drop5}.force, bug7696)
|
|
|
|
end
|
|
|
|
|
2013-01-24 01:23:42 -05:00
|
|
|
def test_drop_nested
|
|
|
|
bug7696 = '[ruby-core:51470]'
|
|
|
|
a = Step.new(1..10)
|
|
|
|
drop5 = a.lazy.drop(5)
|
|
|
|
assert_equal([*(6..10)]*5, drop5.flat_map{drop5}.force, bug7696)
|
|
|
|
end
|
|
|
|
|
2013-01-24 01:24:22 -05:00
|
|
|
def test_zip_nested
|
|
|
|
bug7696 = '[ruby-core:51470]'
|
|
|
|
enum = ('a'..'z').each
|
|
|
|
enum.next
|
|
|
|
zip = (1..3).lazy.zip(enum, enum)
|
|
|
|
assert_equal([[1, 'a', 'a'], [2, 'b', 'b'], [3, 'c', 'c']]*3, zip.flat_map{zip}.force, bug7696)
|
|
|
|
end
|
|
|
|
|
2013-01-24 02:05:42 -05:00
|
|
|
def test_zip_lazy_on_args
|
|
|
|
zip = Step.new(1..2).lazy.zip(42..Float::INFINITY)
|
|
|
|
assert_equal [[1, 42], [2, 43]], zip.force
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_zip_efficient_on_array_args
|
|
|
|
ary = [42, :foo]
|
|
|
|
%i[to_enum enum_for lazy each].each do |forbid|
|
|
|
|
ary.define_singleton_method(forbid){ fail "#{forbid} was called"}
|
|
|
|
end
|
|
|
|
zip = Step.new(1..2).lazy.zip(ary)
|
|
|
|
assert_equal [[1, 42], [2, :foo]], zip.force
|
|
|
|
end
|
|
|
|
|
2013-08-08 11:10:37 -04:00
|
|
|
def test_zip_nonsingle
|
|
|
|
bug8735 = '[ruby-core:56383] [Bug #8735]'
|
|
|
|
|
|
|
|
obj = Object.new
|
|
|
|
def obj.each
|
|
|
|
yield
|
|
|
|
yield 1, 2
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_equal(obj.to_enum.zip(obj.to_enum), obj.to_enum.lazy.zip(obj.to_enum).force, bug8735)
|
|
|
|
end
|
|
|
|
|
2013-01-24 01:22:34 -05:00
|
|
|
def test_take_rewound
|
|
|
|
bug7696 = '[ruby-core:51470]'
|
|
|
|
e=(1..42).lazy.take(2)
|
2014-03-05 08:27:22 -05:00
|
|
|
assert_equal 1, e.next, bug7696
|
|
|
|
assert_equal 2, e.next, bug7696
|
2013-01-24 01:22:34 -05:00
|
|
|
e.rewind
|
2014-03-05 08:27:22 -05:00
|
|
|
assert_equal 1, e.next, bug7696
|
|
|
|
assert_equal 2, e.next, bug7696
|
2013-01-24 01:22:34 -05:00
|
|
|
end
|
|
|
|
|
2012-03-14 09:04:18 -04:00
|
|
|
def test_take_while
|
|
|
|
a = Step.new(1..10)
|
|
|
|
assert_equal(1, a.take_while {|i| i < 5}.first)
|
|
|
|
assert_equal(5, a.current)
|
|
|
|
assert_equal(1, a.lazy.take_while {|i| i < 5}.first)
|
2012-03-14 06:29:25 -04:00
|
|
|
assert_equal(1, a.current)
|
2012-03-14 09:04:18 -04:00
|
|
|
assert_equal((1..4).to_a, a.lazy.take_while {|i| i < 5}.to_a)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_drop
|
|
|
|
a = Step.new(1..10)
|
|
|
|
assert_equal(6, a.drop(5).first)
|
|
|
|
assert_equal(10, a.current)
|
|
|
|
assert_equal(6, a.lazy.drop(5).first)
|
|
|
|
assert_equal(6, a.current)
|
|
|
|
assert_equal((6..10).to_a, a.lazy.drop(5).to_a)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_drop_while
|
|
|
|
a = Step.new(1..10)
|
2013-03-10 16:02:47 -04:00
|
|
|
assert_equal(5, a.drop_while {|i| i % 5 > 0}.first)
|
2012-03-14 09:04:18 -04:00
|
|
|
assert_equal(10, a.current)
|
2013-03-10 16:02:47 -04:00
|
|
|
assert_equal(5, a.lazy.drop_while {|i| i % 5 > 0}.first)
|
2012-03-14 09:04:18 -04:00
|
|
|
assert_equal(5, a.current)
|
2013-03-10 16:02:47 -04:00
|
|
|
assert_equal((5..10).to_a, a.lazy.drop_while {|i| i % 5 > 0}.to_a)
|
2012-03-14 09:04:18 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_drop_and_take
|
|
|
|
assert_equal([4, 5], (1..Float::INFINITY).lazy.drop(3).take(2).to_a)
|
|
|
|
end
|
|
|
|
|
2012-03-14 22:00:30 -04:00
|
|
|
def test_cycle
|
|
|
|
a = Step.new(1..3)
|
|
|
|
assert_equal("1", a.cycle(2).map(&:to_s).first)
|
|
|
|
assert_equal(3, a.current)
|
|
|
|
assert_equal("1", a.lazy.cycle(2).map(&:to_s).first)
|
|
|
|
assert_equal(1, a.current)
|
2012-03-15 05:25:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_cycle_with_block
|
|
|
|
# cycle should be eager when a block is given
|
|
|
|
a = Step.new(1..3)
|
|
|
|
ary = []
|
|
|
|
assert_equal(nil, a.lazy.cycle(2) {|i| ary << i})
|
|
|
|
assert_equal(a.cycle(2).to_a, ary)
|
|
|
|
assert_equal(3, a.current)
|
2012-03-14 22:00:30 -04:00
|
|
|
end
|
|
|
|
|
2012-07-27 04:07:21 -04:00
|
|
|
def test_cycle_chain
|
2012-07-27 04:09:03 -04:00
|
|
|
a = 1..3
|
|
|
|
assert_equal([1,2,3,1,2,3,1,2,3,1], a.lazy.cycle.take(10).force)
|
2012-07-27 04:07:21 -04:00
|
|
|
assert_equal([2,2,2,2,2,2,2,2,2,2], a.lazy.cycle.select {|x| x == 2}.take(10).force)
|
|
|
|
assert_equal([2,2,2,2,2,2,2,2,2,2], a.lazy.select {|x| x == 2}.cycle.take(10).force)
|
|
|
|
end
|
|
|
|
|
2012-03-14 09:04:18 -04:00
|
|
|
def test_force
|
|
|
|
assert_equal([1, 2, 3], (1..Float::INFINITY).lazy.take(3).force)
|
2012-03-14 06:29:25 -04:00
|
|
|
end
|
2012-03-24 11:17:31 -04:00
|
|
|
|
|
|
|
def test_inspect
|
|
|
|
assert_equal("#<Enumerator::Lazy: 1..10>", (1..10).lazy.inspect)
|
2012-11-25 02:39:59 -05:00
|
|
|
assert_equal('#<Enumerator::Lazy: #<Enumerator: "foo":each_char>>',
|
|
|
|
"foo".each_char.lazy.inspect)
|
2012-03-24 11:17:31 -04:00
|
|
|
assert_equal("#<Enumerator::Lazy: #<Enumerator::Lazy: 1..10>:map>",
|
|
|
|
(1..10).lazy.map {}.inspect)
|
2012-03-26 06:52:02 -04:00
|
|
|
assert_equal("#<Enumerator::Lazy: #<Enumerator::Lazy: 1..10>:take(0)>",
|
|
|
|
(1..10).lazy.take(0).inspect)
|
|
|
|
assert_equal("#<Enumerator::Lazy: #<Enumerator::Lazy: 1..10>:take(3)>",
|
|
|
|
(1..10).lazy.take(3).inspect)
|
|
|
|
assert_equal('#<Enumerator::Lazy: #<Enumerator::Lazy: "a".."c">:grep(/b/)>',
|
|
|
|
("a".."c").lazy.grep(/b/).inspect)
|
|
|
|
assert_equal("#<Enumerator::Lazy: #<Enumerator::Lazy: 1..10>:cycle(3)>",
|
|
|
|
(1..10).lazy.cycle(3).inspect)
|
|
|
|
assert_equal("#<Enumerator::Lazy: #<Enumerator::Lazy: 1..10>:cycle>",
|
|
|
|
(1..10).lazy.cycle.inspect)
|
|
|
|
assert_equal("#<Enumerator::Lazy: #<Enumerator::Lazy: 1..10>:cycle(3)>",
|
|
|
|
(1..10).lazy.cycle(3).inspect)
|
|
|
|
l = (1..10).lazy.map {}.collect {}.flat_map {}.collect_concat {}.select {}.find_all {}.reject {}.grep(1).zip(?a..?c).take(10).take_while {}.drop(3).drop_while {}.cycle(3)
|
2012-03-24 11:17:31 -04:00
|
|
|
assert_equal(<<EOS.chomp, l.inspect)
|
2012-03-26 06:52:02 -04:00
|
|
|
#<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: 1..10>:map>:collect>:flat_map>:collect_concat>:select>:find_all>:reject>:grep(1)>:zip("a".."c")>:take(10)>:take_while>:drop(3)>:drop_while>:cycle(3)>
|
2012-03-24 11:17:31 -04:00
|
|
|
EOS
|
|
|
|
end
|
2012-11-06 12:15:59 -05:00
|
|
|
|
2013-02-04 22:49:41 -05:00
|
|
|
def test_lazy_to_enum
|
|
|
|
lazy = [1, 2, 3].lazy
|
|
|
|
def lazy.foo(*args)
|
|
|
|
yield args
|
|
|
|
yield args
|
|
|
|
end
|
|
|
|
enum = lazy.to_enum(:foo, :hello, :world)
|
|
|
|
assert_equal Enumerator::Lazy, enum.class
|
|
|
|
assert_equal nil, enum.size
|
|
|
|
assert_equal [[:hello, :world], [:hello, :world]], enum.to_a
|
|
|
|
|
|
|
|
assert_equal [1, 2, 3], lazy.to_enum.to_a
|
|
|
|
end
|
|
|
|
|
Fix Enumerator::Lazy#{to_enum,enum_for} where method is defined in Lazy
Previously, passing to_enum/enum_for a method that was defined in
Lazy itself returned wrong results:
[1,2,3].to_enum(:map).to_a
# => [1, 2, 3]
[1,2,3].lazy.to_enum(:map).to_a
# => []
I'm not sure why methods that are designed to be lazy do not work
with to_enum/enum_for. However, one possible way to work around
this bug is to have to_enum/enum_for use the implementation found
in Enumerable/Enumerator, which is what this commit does.
While this commit works around the problem, it is a band-aid, not a
real fix. It doesn't handle aliases of Enumerable::Lazy methods,
for instance. A better fix would be appreciated.
2019-09-02 16:22:26 -04:00
|
|
|
def test_lazy_to_enum_lazy_methods
|
|
|
|
a = [1, 2, 3].to_enum
|
|
|
|
pr = proc{|x| [x, x * 2]}
|
|
|
|
selector = proc{|x| x*2 if x % 2 == 0}
|
|
|
|
|
|
|
|
[
|
|
|
|
[:with_index, nil],
|
|
|
|
[:with_index, 10, nil],
|
|
|
|
[:with_index, 10, pr],
|
|
|
|
[:map, nil],
|
|
|
|
[:map, pr],
|
|
|
|
[:collect, nil],
|
|
|
|
[:flat_map, nil],
|
|
|
|
[:flat_map, pr],
|
|
|
|
[:collect_concat, nil],
|
|
|
|
[:select, nil],
|
|
|
|
[:select, selector],
|
|
|
|
[:find_all, nil],
|
|
|
|
[:filter, nil],
|
|
|
|
[:filter_map, selector],
|
|
|
|
[:filter_map, nil],
|
|
|
|
[:reject, selector],
|
|
|
|
[:grep, selector, nil],
|
|
|
|
[:grep, selector, pr],
|
|
|
|
[:grep_v, selector, nil],
|
|
|
|
[:grep_v, selector, pr],
|
|
|
|
[:zip, a, nil],
|
|
|
|
[:take, 3, nil],
|
|
|
|
[:take_while, nil],
|
|
|
|
[:take_while, selector],
|
|
|
|
[:drop, 1, nil],
|
|
|
|
[:drop_while, nil],
|
|
|
|
[:drop_while, selector],
|
|
|
|
[:uniq, nil],
|
|
|
|
[:uniq, proc{|x| x.odd?}],
|
|
|
|
].each do |args|
|
|
|
|
block = args.pop
|
|
|
|
assert_equal [1, 2, 3].to_enum.to_enum(*args).first(2).to_a, [1, 2, 3].to_enum.lazy.to_enum(*args).first(2).to_a
|
|
|
|
assert_equal (0..50).to_enum.to_enum(*args).first(2).to_a, (0..50000).to_enum.lazy.to_enum(*args).first(2).to_a
|
|
|
|
if block
|
|
|
|
assert_equal [1, 2, 3, 4].to_enum.to_enum(*args).map(&block).first(2).to_a, [1, 2, 3, 4].to_enum.lazy.to_enum(*args).map(&block).first(2).to_a
|
|
|
|
unless args.first == :take_while || args.first == :drop_while
|
|
|
|
assert_equal (0..50).to_enum.to_enum(*args).map(&block).first(2).to_a, (0..50000).to_enum.lazy.to_enum(*args).map(&block).first(2).to_a
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-11-06 12:15:59 -05:00
|
|
|
def test_size
|
|
|
|
lazy = [1, 2, 3].lazy
|
|
|
|
assert_equal 3, lazy.size
|
2013-02-04 22:49:41 -05:00
|
|
|
assert_equal 42, Enumerator::Lazy.new([],->{42}){}.size
|
|
|
|
assert_equal 42, Enumerator::Lazy.new([],42){}.size
|
|
|
|
assert_equal 42, Enumerator::Lazy.new([],42){}.lazy.size
|
|
|
|
assert_equal 42, lazy.to_enum{ 42 }.size
|
|
|
|
|
2013-01-13 20:19:12 -05:00
|
|
|
%i[map collect].each do |m|
|
2012-11-06 12:16:13 -05:00
|
|
|
assert_equal 3, lazy.send(m){}.size
|
|
|
|
end
|
|
|
|
assert_equal 3, lazy.zip([4]).size
|
2013-01-13 20:19:12 -05:00
|
|
|
%i[flat_map collect_concat select find_all reject take_while drop_while].each do |m|
|
2012-11-06 12:16:13 -05:00
|
|
|
assert_equal nil, lazy.send(m){}.size
|
|
|
|
end
|
|
|
|
assert_equal nil, lazy.grep(//).size
|
2012-11-06 12:16:29 -05:00
|
|
|
|
|
|
|
assert_equal 2, lazy.take(2).size
|
|
|
|
assert_equal 3, lazy.take(4).size
|
|
|
|
assert_equal 4, loop.lazy.take(4).size
|
|
|
|
assert_equal nil, lazy.select{}.take(4).size
|
2012-11-06 12:16:44 -05:00
|
|
|
|
|
|
|
assert_equal 1, lazy.drop(2).size
|
|
|
|
assert_equal 0, lazy.drop(4).size
|
|
|
|
assert_equal Float::INFINITY, loop.lazy.drop(4).size
|
|
|
|
assert_equal nil, lazy.select{}.drop(4).size
|
2012-11-06 12:16:58 -05:00
|
|
|
|
|
|
|
assert_equal 0, lazy.cycle(0).size
|
|
|
|
assert_equal 6, lazy.cycle(2).size
|
|
|
|
assert_equal 3 << 80, 4.times.inject(lazy){|enum| enum.cycle(1 << 20)}.size
|
|
|
|
assert_equal Float::INFINITY, lazy.cycle.size
|
|
|
|
assert_equal Float::INFINITY, loop.lazy.cycle(4).size
|
|
|
|
assert_equal Float::INFINITY, loop.lazy.cycle.size
|
|
|
|
assert_equal nil, lazy.select{}.cycle(4).size
|
|
|
|
assert_equal nil, lazy.select{}.cycle.size
|
2017-11-05 18:27:46 -05:00
|
|
|
|
|
|
|
class << (obj = Object.new)
|
|
|
|
def each; end
|
|
|
|
def size; 0; end
|
|
|
|
include Enumerable
|
|
|
|
end
|
2017-11-05 18:32:50 -05:00
|
|
|
lazy = obj.lazy
|
|
|
|
assert_equal 0, lazy.cycle.size
|
|
|
|
assert_raise(TypeError) {lazy.cycle("").size}
|
2012-11-06 12:15:59 -05:00
|
|
|
end
|
2012-12-05 08:46:11 -05:00
|
|
|
|
|
|
|
def test_map_zip
|
|
|
|
bug7507 = '[ruby-core:50545]'
|
2013-06-17 20:53:20 -04:00
|
|
|
assert_ruby_status(["-e", "GC.stress = true", "-e", "(1..10).lazy.map{}.zip(){}"], "", bug7507)
|
|
|
|
assert_ruby_status(["-e", "GC.stress = true", "-e", "(1..10).lazy.map{}.zip().to_a"], "", bug7507)
|
2012-12-05 08:46:11 -05:00
|
|
|
end
|
2013-01-14 02:42:43 -05:00
|
|
|
|
|
|
|
def test_require_block
|
2013-01-14 20:40:29 -05:00
|
|
|
%i[select reject drop_while take_while map flat_map].each do |method|
|
2013-01-14 02:42:43 -05:00
|
|
|
assert_raise(ArgumentError){ [].lazy.send(method) }
|
|
|
|
end
|
|
|
|
end
|
2013-02-04 22:49:59 -05:00
|
|
|
|
|
|
|
def test_laziness_conservation
|
|
|
|
bug7507 = '[ruby-core:51510]'
|
|
|
|
{
|
|
|
|
slice_before: //,
|
2014-05-17 20:06:05 -04:00
|
|
|
slice_after: //,
|
2013-02-04 22:49:59 -05:00
|
|
|
with_index: nil,
|
|
|
|
cycle: nil,
|
|
|
|
each_with_object: 42,
|
|
|
|
each_slice: 42,
|
|
|
|
each_entry: nil,
|
|
|
|
each_cons: 42,
|
|
|
|
}.each do |method, arg|
|
|
|
|
assert_equal Enumerator::Lazy, [].lazy.send(method, *arg).class, bug7507
|
|
|
|
end
|
|
|
|
assert_equal Enumerator::Lazy, [].lazy.chunk{}.class, bug7507
|
2014-09-20 02:52:29 -04:00
|
|
|
assert_equal Enumerator::Lazy, [].lazy.slice_when{}.class, bug7507
|
2013-02-04 22:49:59 -05:00
|
|
|
end
|
2013-02-19 22:15:32 -05:00
|
|
|
|
2015-02-28 04:09:18 -05:00
|
|
|
def test_each_cons_limit
|
|
|
|
n = 1 << 120
|
|
|
|
assert_equal([1, 2], (1..n).lazy.each_cons(2).first)
|
|
|
|
assert_equal([[1, 2], [2, 3]], (1..n).lazy.each_cons(2).first(2))
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_each_slice_limit
|
|
|
|
n = 1 << 120
|
|
|
|
assert_equal([1, 2], (1..n).lazy.each_slice(2).first)
|
|
|
|
assert_equal([[1, 2], [3, 4]], (1..n).lazy.each_slice(2).first(2))
|
|
|
|
end
|
|
|
|
|
2013-02-19 22:15:32 -05:00
|
|
|
def test_no_warnings
|
|
|
|
le = (1..3).lazy
|
|
|
|
assert_warning("") {le.zip([4,5,6]).force}
|
|
|
|
assert_warning("") {le.zip(4..6).force}
|
|
|
|
assert_warning("") {le.take(1).force}
|
|
|
|
assert_warning("") {le.drop(1).force}
|
|
|
|
assert_warning("") {le.drop_while{false}.force}
|
|
|
|
end
|
2015-12-16 05:35:34 -05:00
|
|
|
|
|
|
|
def test_symbol_chain
|
|
|
|
assert_equal(["1", "3"], [1, 2, 3].lazy.reject(&:even?).map(&:to_s).force)
|
|
|
|
assert_raise(NoMethodError) do
|
|
|
|
[1, 2, 3].lazy.map(&:undefined).map(&:to_s).force
|
|
|
|
end
|
|
|
|
end
|
2018-03-12 21:00:08 -04:00
|
|
|
|
|
|
|
def test_uniq
|
|
|
|
u = (1..Float::INFINITY).lazy.uniq do |x|
|
|
|
|
raise "too big" if x > 10000
|
|
|
|
(x**2) % 10
|
|
|
|
end
|
|
|
|
assert_equal([1, 2, 3, 4, 5, 10], u.first(6))
|
|
|
|
assert_equal([1, 2, 3, 4, 5, 10], u.first(6))
|
|
|
|
end
|
2019-06-21 03:28:39 -04:00
|
|
|
|
|
|
|
def test_filter_map
|
|
|
|
e = (1..Float::INFINITY).lazy.filter_map do |x|
|
|
|
|
raise "too big" if x > 10000
|
|
|
|
(x**2) % 10 if x.even?
|
|
|
|
end
|
|
|
|
assert_equal([4, 6, 6, 4, 0, 4], e.first(6))
|
|
|
|
assert_equal([4, 6, 6, 4, 0, 4], e.first(6))
|
|
|
|
end
|
2019-08-08 16:09:17 -04:00
|
|
|
|
|
|
|
def test_with_index
|
|
|
|
feature7877 = '[ruby-dev:47025] [Feature #7877]'
|
|
|
|
leibniz = ->(n) {
|
|
|
|
(0..Float::INFINITY).lazy.with_index {|i, j|
|
|
|
|
raise IndexError, "limit exceeded (#{n})" unless j < n
|
|
|
|
((-1) ** j) / (2*i+1).to_f
|
|
|
|
}.take(n).reduce(:+)
|
|
|
|
}
|
|
|
|
assert_nothing_raised(IndexError, feature7877) {
|
|
|
|
assert_in_epsilon(Math::PI/4, leibniz[1000])
|
|
|
|
}
|
|
|
|
|
|
|
|
ary = (0..Float::INFINITY).lazy.with_index(2) {|i, j| [i-1, j] }.take(2).to_a
|
|
|
|
assert_equal([[-1, 2], [0, 3]], ary)
|
|
|
|
|
|
|
|
ary = (0..Float::INFINITY).lazy.with_index(2).take(2).to_a
|
|
|
|
assert_equal([[0, 2], [1, 3]], ary)
|
|
|
|
|
|
|
|
ary = (0..Float::INFINITY).lazy.with_index.take(2).to_a
|
|
|
|
assert_equal([[0, 0], [1, 1]], ary)
|
|
|
|
end
|
2012-03-08 20:13:59 -05:00
|
|
|
end
|