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
}