Upgrade to Pro — share decks privately, control downloads, hide ads and more …

從 Enumerator 看 Ruby 的迭代器

從 Enumerator 看 Ruby 的迭代器

RubyConf TW 2019

蒼時弦や

July 27, 2019
Tweet

More Decks by 蒼時弦や

Other Decks in Programming

Transcript

  1. VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *

    argv, VALUE (*bl_proc) (ANYARGS), VALUE data2) { struct iter_method_arg arg; arg.obj = obj; arg.mid = mid; arg.argc = argc; arg.argv = argv; return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2); } The block call is iterate in ruby
  2. static VALUE loop_i(void) { for (;;) { rb_yield_0(0, 0); }

    return Qnil; } Loop is a method with a block
  3. class Backpack include Enumerable def initialize(items) @items = items end

    def each(&block) @items.each(&block) end end backpack = Backpack.new([:water, :apple]) backpack.map {}
  4. class List def each(&block) #... end end List.new.to_enum # =>

    #<Enumerator: #<List:0x00007fa490988a78>:each>
  5. class List def pop(&block) #... end end List.new.to_enum(:pop) # =>

    #<Enumerator: #<List:0x00007fa491081fa0>:pop>
  6. enum = Enumerator.new do yield 1 yield 2 end puts

    enum.to_a # => no block given (yield) (LocalJumpError)
  7. class Generator def initialize(&block) @proc = block.to_proc end def each(&_block)

    yielder = Yielder.new { |x| yield x } @proc.call(yielder) end end
  8. class Backpack def each(&block) yield p(1) yield p(2) yield p(3)

    end end backpack = Backpack.new.to_enum backpack.map(&:rect).take(1).to_a backpack.lazy.map(&:rect).take(1).to_a
  9. class Backpack def each(&block) yield p(1) yield p(2) yield p(3)

    end end backpack = Backpack.new.to_enum backpack.map(&:rect).take(1).to_a backpack.lazy.map(&:rect).take(1).to_a
  10. backpack.map(&:rect).take(1).to_a # => 1 # => 2 # => 3

    backpack.lazy.map(&:rect).take(1).to_a # => 1