* enum.c: Support for enumerators created by Enumerable with forwarding:
find_all, reject, ... [Feature #6636] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37507 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
727024fbac
commit
c82ad6d207
36
enum.c
36
enum.c
@ -305,6 +305,14 @@ find_all_i(VALUE i, VALUE ary, int argc, VALUE *argv)
|
|||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
enum_size(VALUE self, VALUE args)
|
||||||
|
{
|
||||||
|
VALUE r;
|
||||||
|
r = rb_check_funcall(self, id_size, 0, 0);
|
||||||
|
return (r == Qundef) ? Qnil : r;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* enum.find_all { |obj| block } -> array
|
* enum.find_all { |obj| block } -> array
|
||||||
@ -330,7 +338,7 @@ enum_find_all(VALUE obj)
|
|||||||
{
|
{
|
||||||
VALUE ary;
|
VALUE ary;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
ary = rb_ary_new();
|
ary = rb_ary_new();
|
||||||
rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
|
rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
|
||||||
@ -371,7 +379,7 @@ enum_reject(VALUE obj)
|
|||||||
{
|
{
|
||||||
VALUE ary;
|
VALUE ary;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
ary = rb_ary_new();
|
ary = rb_ary_new();
|
||||||
rb_block_call(obj, id_each, 0, 0, reject_i, ary);
|
rb_block_call(obj, id_each, 0, 0, reject_i, ary);
|
||||||
@ -418,7 +426,7 @@ enum_collect(VALUE obj)
|
|||||||
{
|
{
|
||||||
VALUE ary;
|
VALUE ary;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
ary = rb_ary_new();
|
ary = rb_ary_new();
|
||||||
rb_block_call(obj, id_each, 0, 0, collect_i, ary);
|
rb_block_call(obj, id_each, 0, 0, collect_i, ary);
|
||||||
@ -465,7 +473,7 @@ enum_flat_map(VALUE obj)
|
|||||||
{
|
{
|
||||||
VALUE ary;
|
VALUE ary;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
ary = rb_ary_new();
|
ary = rb_ary_new();
|
||||||
rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
|
rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
|
||||||
@ -640,7 +648,7 @@ enum_partition(VALUE obj)
|
|||||||
{
|
{
|
||||||
NODE *memo;
|
NODE *memo;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
memo = NEW_MEMO(rb_ary_new(), rb_ary_new(), 0);
|
memo = NEW_MEMO(rb_ary_new(), rb_ary_new(), 0);
|
||||||
rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
|
rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
|
||||||
@ -688,7 +696,7 @@ enum_group_by(VALUE obj)
|
|||||||
{
|
{
|
||||||
VALUE hash;
|
VALUE hash;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
hash = rb_hash_new();
|
hash = rb_hash_new();
|
||||||
rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
|
rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
|
||||||
@ -897,7 +905,7 @@ enum_sort_by(VALUE obj)
|
|||||||
long i;
|
long i;
|
||||||
struct sort_by_data *data;
|
struct sort_by_data *data;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
|
if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
|
||||||
ary = rb_ary_new2(RARRAY_LEN(obj)*2);
|
ary = rb_ary_new2(RARRAY_LEN(obj)*2);
|
||||||
@ -1437,7 +1445,7 @@ enum_min_by(VALUE obj)
|
|||||||
{
|
{
|
||||||
NODE *memo;
|
NODE *memo;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
memo = NEW_MEMO(Qundef, Qnil, 0);
|
memo = NEW_MEMO(Qundef, Qnil, 0);
|
||||||
rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
|
rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
|
||||||
@ -1483,7 +1491,7 @@ enum_max_by(VALUE obj)
|
|||||||
{
|
{
|
||||||
NODE *memo;
|
NODE *memo;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
memo = NEW_MEMO(Qundef, Qnil, 0);
|
memo = NEW_MEMO(Qundef, Qnil, 0);
|
||||||
rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
|
rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
|
||||||
@ -1581,7 +1589,7 @@ enum_minmax_by(VALUE obj)
|
|||||||
VALUE memo;
|
VALUE memo;
|
||||||
struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);
|
struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, 0, 0);
|
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
|
||||||
|
|
||||||
m->min_bv = Qundef;
|
m->min_bv = Qundef;
|
||||||
m->max_bv = Qundef;
|
m->max_bv = Qundef;
|
||||||
@ -1662,7 +1670,7 @@ enum_each_with_index(int argc, VALUE *argv, VALUE obj)
|
|||||||
{
|
{
|
||||||
NODE *memo;
|
NODE *memo;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, argc, argv);
|
RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
|
||||||
|
|
||||||
memo = NEW_MEMO(0, 0, 0);
|
memo = NEW_MEMO(0, 0, 0);
|
||||||
rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
|
rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
|
||||||
@ -1694,7 +1702,7 @@ enum_reverse_each(int argc, VALUE *argv, VALUE obj)
|
|||||||
VALUE ary;
|
VALUE ary;
|
||||||
long i;
|
long i;
|
||||||
|
|
||||||
RETURN_ENUMERATOR(obj, argc, argv);
|
RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
|
||||||
|
|
||||||
ary = enum_to_a(argc, argv, obj);
|
ary = enum_to_a(argc, argv, obj);
|
||||||
|
|
||||||
@ -1746,7 +1754,7 @@ each_val_i(VALUE i, VALUE p, int argc, VALUE *argv)
|
|||||||
static VALUE
|
static VALUE
|
||||||
enum_each_entry(int argc, VALUE *argv, VALUE obj)
|
enum_each_entry(int argc, VALUE *argv, VALUE obj)
|
||||||
{
|
{
|
||||||
RETURN_ENUMERATOR(obj, argc, argv);
|
RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
|
||||||
rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
|
rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -1882,7 +1890,7 @@ each_with_object_i(VALUE i, VALUE memo, int argc, VALUE *argv)
|
|||||||
static VALUE
|
static VALUE
|
||||||
enum_each_with_object(VALUE obj, VALUE memo)
|
enum_each_with_object(VALUE obj, VALUE memo)
|
||||||
{
|
{
|
||||||
RETURN_ENUMERATOR(obj, 1, &memo);
|
RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enum_size);
|
||||||
|
|
||||||
rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
|
rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
|
||||||
|
|
||||||
|
@ -10,6 +10,10 @@ class TestEnumerator < Test::Unit::TestCase
|
|||||||
a.each {|x| yield x }
|
a.each {|x| yield x }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@sized = @obj.clone
|
||||||
|
def @sized.size
|
||||||
|
42
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def enum_test obj
|
def enum_test obj
|
||||||
@ -429,6 +433,16 @@ class TestEnumerator < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_size_for_enum_created_from_enumerable
|
||||||
|
%i[find_all reject map flat_map partition group_by sort_by min_by max_by
|
||||||
|
minmax_by each_with_index reverse_each each_entry].each do |method|
|
||||||
|
assert_equal nil, @obj.send(method).size
|
||||||
|
assert_equal 42, @sized.send(method).size
|
||||||
|
end
|
||||||
|
assert_equal nil, @obj.each_with_object(nil).size
|
||||||
|
assert_equal 42, @sized.each_with_object(nil).size
|
||||||
|
end
|
||||||
|
|
||||||
def check_consistency_for_combinatorics(method)
|
def check_consistency_for_combinatorics(method)
|
||||||
[ [], [:a, :b, :c, :d, :e] ].product([-2, 0, 2, 5, 6]) do |array, arg|
|
[ [], [:a, :b, :c, :d, :e] ].product([-2, 0, 2, 5, 6]) do |array, arg|
|
||||||
assert_equal array.send(method, arg).to_a.size, array.send(method, arg).size,
|
assert_equal array.send(method, arg).to_a.size, array.send(method, arg).size,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user