Project

General

Profile

Feature #15618 ยป 0001-Implement-Enumerator-Yielder-to_proc.patch

knu (Akinori MUSHA), 02/24/2019 03:14 PM

View differences:

enumerator.c
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
......
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))
{
......
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);
......
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);
}
test/ruby/test_enumerator.rb
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
    (1-1/1)