Enumerator::Lazy

class Enumerator::Lazy

Parent:
Enumerator

Lazy

Public Class Methods

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

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

Public Instance Methods

chunk(*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_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_map_func, 0),
                           Qnil, lazy_receiver_size);
}
collect_concat { |obj| block } → a_lazy_enumerator Show source

Returns a new lazy enumerator with the concatenated results of running block once for every element in lazy.

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

A value x returned by block is decomposed if either of the following conditions is true:

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.

Otherwise, x is contained as-is in the return value.

[{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_func, 0),
                           Qnil, 0);
}
drop(p1) Show source
static VALUE
lazy_drop(VALUE obj, VALUE n)
{
    long len = NUM2LONG(n);

    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to drop negative size");
    }
    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_drop_func, n),
                           rb_ary_new3(1, n), lazy_drop_size);
}
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_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_drop_while_func, 0),
                           Qnil, 0);
}
enum_for(method = :each, *args) → lazy_enum Show source
enum_for(method = :each, *args){|*args| block} → lazy_enum

Similar to Kernel#to_enum, except it returns a lazy enumerator. This makes it easy to define Enumerable methods that will naturally remain lazy if called from a lazy enumerator.

For example, continuing from the example in 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_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_select_func, 0),
                           Qnil, 0);
}
flat_map { |obj| block } → a_lazy_enumerator Show source

Returns a new lazy enumerator with the concatenated results of running block once for every element in lazy.

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

A value x returned by block is decomposed if either of the following conditions is true:

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.

Otherwise, x is contained as-is in the return value.

[{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_func, 0),
                           Qnil, 0);
}
grep(p1) Show source
static VALUE
lazy_grep(VALUE obj, VALUE pattern)
{
    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         rb_block_given_p() ?
                                         lazy_grep_iter : lazy_grep_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_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_map_func, 0),
                           Qnil, lazy_receiver_size);
}
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_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_reject_func, 0),
                           Qnil, 0);
}
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_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_select_func, 0),
                           Qnil, 0);
}
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);
    VALUE lazy;

    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to take negative size");
    }
    if (len == 0) {
        VALUE len = INT2FIX(0);
        lazy = lazy_to_enum_i(obj, sym_cycle, 1, &len, 0);
    }
    else {
        lazy = rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_take_func, n);
    }
    return lazy_set_method(lazy, rb_ary_new3(1, n), lazy_take_size);
}
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_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_take_while_func, 0),
                           Qnil, 0);
}
to_enum(method = :each, *args) → lazy_enum Show source
to_enum(method = :each, *args) {|*args| block} → lazy_enum

Similar to Kernel#to_enum, except it returns a lazy enumerator. This makes it easy to define Enumerable methods that will naturally remain lazy if called from a lazy enumerator.

For example, continuing from the example in 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;
}
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 %s (must respond to :each)",
                        rb_obj_classname(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);
}

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号

意见反馈
返回顶部