static VALUE lazy_initialize(int argc, VALUE *argv, VALUE self) { VALUE obj, meth; VALUE generator; int offset; if (argc < 1) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..)", argc); } else { obj = argv[0]; if (argc == 1) { meth = sym_each; offset = 1; } else { meth = argv[1]; offset = 2; } } generator = generator_allocate(rb_cGenerator); rb_block_call(generator, id_initialize, 0, 0, (rb_block_given_p() ? lazy_init_block_i : lazy_init_block), obj); enumerator_init(self, generator, meth, argc - offset, argv + offset); rb_ivar_set(self, id_receiver, obj); return self; }
/* * call-seq: * Enumerator.new(size = nil) { |yielder| ... } * Enumerator.new(obj, method = :each, *args) * * Creates a new Enumerator object, which can be used as an * Enumerable. * * In the first form, iteration is defined by the given block, in * which a "yielder" object, given as block parameter, can be used to * yield a value by calling the +yield+ method (aliased as +<<+): * * fib = Enumerator.new do |y| * a = b = 1 * loop do * y << a * a, b = b, a + b * end * end * * p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] * * The optional parameter can be used to specify how to calculate the size * in a lazy fashion (see Enumerator#size). It can either be a value or * a callable object. * * In the second, deprecated, form, a generated Enumerator iterates over the * given object using the given method with the given arguments passed. * * Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum * instead. * * e = Enumerator.new(ObjectSpace, :each_object) * #-> ObjectSpace.enum_for(:each_object) * * e.select { |obj| obj.is_a?(Class) } #=> array of all classes * */ static VALUE enumerator_initialize(int argc, VALUE *argv, VALUE obj) { VALUE recv, meth = sym_each; VALUE size = Qnil; if (rb_block_given_p()) { rb_check_arity(argc, 0, 1); recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc()); if (argc) { if (NIL_P(argv[0]) || rb_obj_is_proc(argv[0]) || (RB_TYPE_P(argv[0], T_FLOAT) && RFLOAT_VALUE(argv[0]) == INFINITY)) { size = argv[0]; } else { size = rb_to_int(argv[0]); } argc = 0; } } else { rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); rb_warn("Enumerator.new without a block is deprecated; use Object#to_enum"); recv = *argv++; if (--argc) { meth = *argv++; --argc; } } return enumerator_init(obj, recv, meth, argc, argv, 0, size); }
VALUE rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, VALUE *argv, rb_enumerator_size_func *size_fn) { /* Similar effect as calling obj.to_enum, i.e. dispatching to either Kernel#to_enum vs Lazy#to_enum */ if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy))) return lazy_to_enum_i(obj, meth, argc, argv, size_fn); else return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, meth, argc, argv, size_fn, Qnil); }
static struct enumerator *parse_enumerator(struct parser *parser) { union token id_tok = expect(parser->lexer, TOK_IDENTIFIER); union token tok = lexer_next_token(parser->lexer); struct constant_expression *expr = NULL; if (tok.tok_tag == TOK_ASSIGN) { expr = parse_constant_expression(parser); } else { lexer_put_back(parser->lexer, tok); } return enumerator_init(id_tok.id.s, expr); }
/* * call-seq: * Enumerable::Enumerator.new(obj, method = :each, *args) * * Creates a new Enumerable::Enumerator object, which is to be * used as an Enumerable object using the given object's given * method with the given arguments. * * e.g.: * str = "xyz" * * enum = Enumerable::Enumerator.new(str, :each_byte) * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"] * */ static VALUE enumerator_initialize(int argc, VALUE *argv, VALUE obj) { VALUE recv, meth = sym_each; if (argc == 0) rb_raise(rb_eArgError, "wrong number of argument (0 for 1)"); recv = *argv++; if (--argc) { meth = *argv++; --argc; } return enumerator_init(obj, recv, meth, argc, argv); }
/* * call-seq: * Enumerator.new(obj, method = :each, *args) * Enumerator.new { |y| ... } * * Creates a new Enumerator object, which is to be used as an * Enumerable object iterating in a given way. * * In the first form, a generated Enumerator iterates over the given * object using the given method with the given arguments passed. * Use of this form is discouraged. Use Kernel#enum_for(), alias * to_enum, instead. * * e = Enumerator.new(ObjectSpace, :each_object) * #-> ObjectSpace.enum_for(:each_object) * * e.select { |obj| obj.is_a?(Class) } #=> array of all classes * * In the second form, iteration is defined by the given block, in * which a "yielder" object given as block parameter can be used to * yield a value by calling the +yield+ method, alias +<<+. * * fib = Enumerator.new { |y| * a = b = 1 * loop { * y << a * a, b = b, a + b * } * } * * p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] */ static VALUE enumerator_initialize(int argc, VALUE *argv, VALUE obj) { VALUE recv, meth = sym_each; if (argc == 0) { if (!rb_block_given_p()) rb_raise(rb_eArgError, "wrong number of argument (0 for 1+)"); recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc()); } else { recv = *argv++; if (--argc) { meth = *argv++; --argc; } } return enumerator_init(obj, recv, meth, argc, argv); }
/* * call-seq: * Lazy.new(obj, size=nil) { |yielder, *values| ... } * * Creates a new Lazy enumerator. When the enumerator is actually enumerated * (e.g. by calling #force), +obj+ will be enumerated and each value passed * to the given block. The block can yield values back using +yielder+. * For example, to create a method +filter_map+ in both lazy and * non-lazy fashions: * * module Enumerable * def filter_map(&block) * map(&block).compact * end * end * * class Enumerator::Lazy * def filter_map * Lazy.new(self) do |yielder, *values| * result = yield *values * yielder << result if result * end * end * end * * (1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(5) * # => [4, 16, 36, 64, 100] */ static VALUE lazy_initialize(int argc, VALUE *argv, VALUE self) { VALUE obj, size = Qnil; VALUE generator; rb_check_arity(argc, 1, 2); if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy new without a block"); } obj = argv[0]; if (argc > 1) { size = argv[1]; } generator = generator_allocate(rb_cGenerator); rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj); enumerator_init(self, generator, sym_each, 0, 0, 0, size); rb_ivar_set(self, id_receiver, obj); return self; }
/* * call-seq: * Enumerator.new { |yielder| ... } * Enumerator.new(obj, method = :each, *args) * * Creates a new Enumerator object, which can be used as an * Enumerable. * * In the first form, iteration is defined by the given block, in * which a "yielder" object, given as block parameter, can be used to * yield a value by calling the +yield+ method (aliased as +<<+): * * fib = Enumerator.new do |y| * a = b = 1 * loop do * y << a * a, b = b, a + b * end * end * * p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] * * The block form can be used to create a lazy enumeration that only processes * elements as-needed. The generic pattern for this is: * * Enumerator.new do |yielder| * source.each do |source_item| * # process source_item and append the yielder * end * end * * This can be used with infinite streams to support multiple chains: * * class Fib * def initialize(a = 1, b = 1) * @a, @b = a, b * end * * def each * a, b = @a, @b * yield a * while true * yield b * a, b = b, a+b * end * end * end * * def lazy_select enum * Enumerator.new do |y| * enum.each do |e| * y << e if yield e * end * end * end * * def lazy_map enum * Enumerator.new do |y| * enum.each do |e| * y << yield(e) * end * end * end * * even_fibs = lazy_select(Fibs.new) { |x| x % 2 == 0 } * string_fibs = lazy_map(even_fibs) { |x| "<#{x}>" } * string_fibs.each_with_index do |fib, i| * puts "#{i}: #{fib}" * break if i >= 3 * end * * This allows output even though the Fib produces an infinite sequence of * Fibonacci numbers: * * 0: <2> * 1: <8> * 2: <34> * 3: <144> * * In the second, deprecated, form, a generated Enumerator iterates over the * given object using the given method with the given arguments passed. * * Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum * instead. * * e = Enumerator.new(ObjectSpace, :each_object) * #-> ObjectSpace.enum_for(:each_object) * * e.select { |obj| obj.is_a?(Class) } #=> array of all classes * */ static VALUE enumerator_initialize(int argc, VALUE *argv, VALUE obj) { VALUE recv, meth = sym_each; if (argc == 0) { if (!rb_block_given_p()) rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc()); } else { recv = *argv++; if (--argc) { meth = *argv++; --argc; } } return enumerator_init(obj, recv, meth, argc, argv); }
/* * call-seq: * Enumerator.new(obj, method = :each, *args) * Enumerator.new { |y| ... } * * Creates a new Enumerator object, which is to be used as an * Enumerable object iterating in a given way. * * In the first form, a generated Enumerator iterates over the given * object using the given method with the given arguments passed. * Use of this form is discouraged. Use Kernel#enum_for(), alias * to_enum, instead. * * e = Enumerator.new(ObjectSpace, :each_object) * #-> ObjectSpace.enum_for(:each_object) * * e.select { |obj| obj.is_a?(Class) } #=> array of all classes * * In the second form, iteration is defined by the given block, in * which a "yielder" object given as block parameter can be used to * yield a value by calling the +yield+ method, alias +<<+. * * fib = Enumerator.new { |y| * a = b = 1 * loop { * y << a * a, b = b, a + b * } * } * * p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] */ static VALUE enumerator_initialize(VALUE obj, SEL sel, int argc, VALUE *argv) { VALUE recv, meth = sym_each; if (argc == 0) { if (!rb_block_given_p()) rb_raise(rb_eArgError, "wrong number of argument (0 for 1+)"); recv = generator_init(generator_allocate(rb_cGenerator, 0), rb_block_proc()); } else { recv = *argv++; if (--argc) { meth = *argv++; --argc; } } ID meth_id = rb_to_id(meth); SEL meth_sel = rb_vm_id_to_sel(meth_id, argc); return enumerator_init(obj, recv, meth_sel, argc, argv); }
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv) { return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, meth, argc, argv); }
static VALUE lazy_to_enum_i(VALUE obj, VALUE meth, int argc, VALUE *argv, rb_enumerator_size_func *size_fn) { return enumerator_init(enumerator_allocate(rb_cLazy), obj, meth, argc, argv, size_fn, Qnil); }
VALUE rb_enumeratorize(VALUE obj, SEL sel, int argc, VALUE *argv) { return enumerator_init(enumerator_allocate(rb_cEnumerator, 0), obj, sel, argc, argv); }