Ruby 2.4

Enumerator::Lazy

class Enumerator::Lazy

Parent:Enumerator

Lazy

公共类方法

new(obj, size=nil) { |yielder, *values| ... } Show source

创建一个新的Lazy枚举器。当枚举数实际枚举(例如通过调用force)时,obj将被枚举并将每个值传递给给定的块。该块可以返回使用的值yielder。例如,要以filter_map惰性和非惰性的方式创建一个方法:

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; }

公共实例方法

chunk(*args) Show source

static VALUE lazy_super(int argc, VALUE *argv, VALUE lazy) { return enumerable_lazy(rb_call_super(argc, argv) }

chunk_while(*args) Show source

static VALUE lazy_super(int argc, VALUE *argv, VALUE lazy) { return enumerable_lazy(rb_call_super(argc, argv) }

collect() Show source

static VALUE lazy_map(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy map without a block" } return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_map_funcs }

collect_concat { |obj| block } → a_lazy_enumerator Show source

返回一个新的惰性枚举器,其中每个元素都为一个惰性运行的连续结果。

["foo", "bar"].lazy.flat_map {|i| i.each_char.lazy}.force #=> ["f", "o", "o", "b", "a", "r"]

如果满足以下任一条件,则返回的值x将被分解:

a) <i>x</i> responds to both each and force, which means that <i>x</i> is a lazy enumerator. b) <i>x</i> is an array or responds to to_ary.

否则,x被包含在返回值中。

[{a:1}, {b:2}].lazy.flat_map {|i| i}.force #=> [{:a=>1}, {:b=>2}]

static VALUE lazy_flat_map(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy flat_map without a block" } return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, lazy_flat_map_proc, 0), Qnil, 0 }

drop(p1) Show source

static VALUE lazy_drop(VALUE obj, VALUE n) { long len = NUM2LONG(n VALUE argv[2]; argv[0] = sym_each; argv[1] = n; if (len < 0) { rb_raise(rb_eArgError, "attempt to drop negative size" } return lazy_add_method(obj, 2, argv, n, rb_ary_new3(1, n), &lazy_drop_funcs }

drop_while() Show source

static VALUE lazy_drop_while(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy drop_while without a block" } return lazy_add_method(obj, 0, 0, Qfalse, Qnil, &lazy_drop_while_funcs }

enum_for(method = :each, *args) → lazy_enum Show source

enum_for(method = :each, *args){|*args| block} → lazy_enum

与Kernel#to_enum类似,只不过它返回一个惰性的枚举器。这可以很容易地定义Enumerable方法,如果从惰性枚举器调用,它自然会保持惰性。

例如,Kernel#to_enum中的示例:

# See Kernel#to_enum for the definition of repeat r = 1..Float::INFINITY r.repeat(2).first(5) # => [1, 1, 2, 2, 3] r.repeat(2).class # => Enumerator r.repeat(2).map{|n| n ** 2}.first(5) # => endless loop! # works naturally on lazy enumerator: r.lazy.repeat(2).class # => Enumerator::Lazy r.lazy.repeat(2).map{|n| n ** 2}.first(5) # => [1, 1, 4, 4, 9]

static VALUE lazy_to_enum(int argc, VALUE *argv, VALUE self) { VALUE lazy, meth = sym_each; if (argc > 0) { --argc; meth = *argv++; } lazy = lazy_to_enum_i(self, meth, argc, argv, 0 if (rb_block_given_p()) { enumerator_ptr(lazy)->size = rb_block_proc( } return lazy; }

find_all() Show source

static VALUE lazy_select(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy select without a block" } return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_select_funcs }

flat_map { |obj| block } → a_lazy_enumerator Show source

返回一个新的惰性枚举器,其中每个元素都为一个惰性运行的连续结果。

["foo", "bar"].lazy.flat_map {|i| i.each_char.lazy}.force #=> ["f", "o", "o", "b", "a", "r"]

如果满足以下任一条件,则返回的值x 将被分解:

a) <i>x</i> responds to both each and force, which means that <i>x</i> is a lazy enumerator. b) <i>x</i> is an array or responds to to_ary.

否则,x被包含在返回值中。

[{a:1}, {b:2}].lazy.flat_map {|i| i}.force #=> [{:a=>1}, {:b=>2}]

static VALUE lazy_flat_map(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy flat_map without a block" } return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, lazy_flat_map_proc, 0), Qnil, 0 }

grep(p1) Show source

static VALUE lazy_grep(VALUE obj, VALUE pattern) { const lazyenum_funcs *const funcs = rb_block_given_p() ? &lazy_grep_iter_funcs : &lazy_grep_funcs; return lazy_add_method(obj, 0, 0, pattern, rb_ary_new3(1, pattern), funcs }

grep_v(p1) Show source

static VALUE lazy_grep_v(VALUE obj, VALUE pattern) { return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, rb_block_given_p() ? lazy_grep_v_iter : lazy_grep_v_func, pattern), rb_ary_new3(1, pattern), 0 }

lazy() Show source

static VALUE lazy_lazy(VALUE obj) { return obj; }

map() Show source

static VALUE lazy_map(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy map without a block" } return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_map_funcs }

reject() Show source

static VALUE lazy_reject(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy reject without a block" } return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_reject_funcs }

select() Show source

static VALUE lazy_select(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy select without a block" } return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_select_funcs }

slice_after(*args) Show source

static VALUE lazy_super(int argc, VALUE *argv, VALUE lazy) { return enumerable_lazy(rb_call_super(argc, argv) }

slice_before(*args) Show source

static VALUE lazy_super(int argc, VALUE *argv, VALUE lazy) { return enumerable_lazy(rb_call_super(argc, argv) }

slice_when(*args) Show source

static VALUE lazy_super(int argc, VALUE *argv, VALUE lazy) { return enumerable_lazy(rb_call_super(argc, argv) }

take(p1) Show source

static VALUE lazy_take(VALUE obj, VALUE n) { long len = NUM2LONG(n int argc = 0; VALUE argv[2]; if (len < 0) { rb_raise(rb_eArgError, "attempt to take negative size" } if (len == 0) { argv[0] = sym_cycle; argv[1] = INT2NUM(0 argc = 2; } return lazy_add_method(obj, argc, argv, n, rb_ary_new3(1, n), &lazy_take_funcs }

take_while() Show source

static VALUE lazy_take_while(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "tried to call lazy take_while without a block" } return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_take_while_funcs }

to_enum(method = :each, *args) → lazy_enum Show source

to_enum(method = :each, *args) {|*args| block} → lazy_enum

与Kernel#to_enum类似,只不过它返回一个惰性枚举器。这可以很容易地定义Enumerable方法,如果从惰性枚举器调用,它自然会保持惰性。

例如,Kernel#to_enum中的示例:

# See Kernel#to_enum for the definition of repeat r = 1..Float::INFINITY r.repeat(2).first(5) # => [1, 1, 2, 2, 3] r.repeat(2).class # => Enumerator r.repeat(2).map{|n| n ** 2}.first(5) # => endless loop! # works naturally on lazy enumerator: r.lazy.repeat(2).class # => Enumerator::Lazy r.lazy.repeat(2).map{|n| n ** 2}.first(5) # => [1, 1, 4, 4, 9]

static VALUE lazy_to_enum(int argc, VALUE *argv, VALUE self) { VALUE lazy, meth = sym_each; if (argc > 0) { --argc; meth = *argv++; } lazy = lazy_to_enum_i(self, meth, argc, argv, 0 if (rb_block_given_p()) { enumerator_ptr(lazy)->size = rb_block_proc( } return lazy; }

uniq() Show source

static VALUE lazy_uniq(VALUE obj) { rb_block_call_func *const func = rb_block_given_p() ? lazy_uniq_iter : lazy_uniq_func; VALUE hash = rb_obj_hide(rb_hash_new() return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, func, hash), 0, 0 }

zip(*args) Show source

static VALUE lazy_zip(int argc, VALUE *argv, VALUE obj) { VALUE ary, v; long i; rb_block_call_func *func = lazy_zip_arrays_func; if (rb_block_given_p()) { return rb_call_super(argc, argv } ary = rb_ary_new2(argc for (i = 0; i < argc; i++) { v = rb_check_array_type(argv[i] if (NIL_P(v)) { for (; i < argc; i++) { if (!rb_respond_to(argv[i], id_each)) { rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)", rb_obj_class(argv[i]) } } ary = rb_ary_new4(argc, argv func = lazy_zip_func; break; } rb_ary_push(ary, v } return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, func, ary), ary, lazy_receiver_size }