зеркало из https://github.com/github/ruby.git
Implement Enumerator::Yielder#to_proc
A Yielder object can now be directly passed to another method as a block argument. ```ruby enum = Enumerator.new { |y| Dir.glob("*.rb") { |file| File.open(file) { |f| f.each_line(&y) } } } ``` git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67211 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
7d9664953b
Коммит
c2d3b8dfb4
27
enumerator.c
27
enumerator.c
|
@ -110,8 +110,8 @@ VALUE rb_cEnumerator;
|
|||
static VALUE rb_cLazy;
|
||||
static ID id_rewind, id_new, id_to_enum;
|
||||
static ID id_next, id_result, id_receiver, id_arguments, id_memo, id_method, id_force;
|
||||
static ID id_begin, id_end, id_step, id_exclude_end;
|
||||
static VALUE sym_each, sym_cycle;
|
||||
static ID id_begin, id_end, id_step, id_exclude_end, id_to_proc;
|
||||
static VALUE sym_each, sym_cycle, sym_yield;
|
||||
|
||||
#define id_call idCall
|
||||
#define id_each idEach
|
||||
|
@ -1288,6 +1288,26 @@ yielder_yield_push(VALUE obj, VALUE arg)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a Proc object that takes an argument and yields it.
|
||||
*
|
||||
* This method is implemented so that a Yielder object can be directly
|
||||
* passed to another method as a block argument.
|
||||
*
|
||||
* enum = Enumerator.new { |y|
|
||||
* Dir.glob("*.rb") { |file|
|
||||
* File.open(file) { |f| f.each_line(&y) }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
static VALUE
|
||||
yielder_to_proc(VALUE obj)
|
||||
{
|
||||
VALUE method = rb_obj_method(obj, sym_yield);
|
||||
|
||||
return rb_funcall(method, id_to_proc, 0);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
yielder_yield_i(RB_BLOCK_CALL_FUNC_ARGLIST(obj, memo))
|
||||
{
|
||||
|
@ -3380,6 +3400,7 @@ InitVM_Enumerator(void)
|
|||
rb_define_method(rb_cYielder, "initialize", yielder_initialize, 0);
|
||||
rb_define_method(rb_cYielder, "yield", yielder_yield, -2);
|
||||
rb_define_method(rb_cYielder, "<<", yielder_yield_push, 1);
|
||||
rb_define_method(rb_cYielder, "to_proc", yielder_to_proc, 0);
|
||||
|
||||
/* Chain */
|
||||
rb_cEnumChain = rb_define_class_under(rb_cEnumerator, "Chain", rb_cEnumerator);
|
||||
|
@ -3430,8 +3451,10 @@ Init_Enumerator(void)
|
|||
id_end = rb_intern("end");
|
||||
id_step = rb_intern("step");
|
||||
id_exclude_end = rb_intern("exclude_end");
|
||||
id_to_proc = rb_intern("to_proc");
|
||||
sym_each = ID2SYM(id_each);
|
||||
sym_cycle = ID2SYM(rb_intern("cycle"));
|
||||
sym_yield = ID2SYM(rb_intern("yield"));
|
||||
|
||||
InitVM(Enumerator);
|
||||
}
|
||||
|
|
|
@ -493,6 +493,21 @@ class TestEnumerator < Test::Unit::TestCase
|
|||
assert_equal([1, 2, 3], y.yield(2, 3))
|
||||
|
||||
assert_raise(LocalJumpError) { Enumerator::Yielder.new }
|
||||
|
||||
# to_proc (explicit)
|
||||
a = []
|
||||
y = Enumerator::Yielder.new {|x| a << x }
|
||||
b = y.to_proc
|
||||
assert_kind_of(Proc, b)
|
||||
assert_equal([1], b.call(1))
|
||||
assert_equal([1], a)
|
||||
|
||||
# to_proc (implicit)
|
||||
e = Enumerator.new { |y|
|
||||
assert_kind_of(Enumerator::Yielder, y)
|
||||
[1, 2, 3].each(&y)
|
||||
}
|
||||
assert_equal([1, 2, 3], e.to_a)
|
||||
end
|
||||
|
||||
def test_size
|
||||
|
|
Загрузка…
Ссылка в новой задаче