Array#如何在Ruby中实现?

时间:2014-08-05 13:35:35

标签: ruby

我很好奇Ruby中的收集和阻止机制。我们可以定义一个这样的类:

class Foo
    include Enumerable
    def initialize
        @data = []
    end

    def each
        if block_given?
            @data.each { |e| yield(e) }
        else
            Enumerator.new(self, :each)
        end
    end 
end

我想知道@data.each如何使用块{ |e| yield(e) }作为参数。我搜索了Array#each:

的实现
rb_ary_each(VALUE array)
{
    long i;
    volatile VALUE ary = array;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    for (i=0; i<RARRAY_LEN(ary); i++) {
        rb_yield(RARRAY_AREF(ary, i));
    }
    return ary;
}

但这似乎并不像Ruby语言实现。如何在Ruby中实现Array#each

编辑:

看起来C代码遍历第一个到最后一个数组元素,并使用遍历数组元素的参数调用ruby yield函数。但是块传递到rb_ary_each函数的哪个位置?

2 个答案:

答案 0 :(得分:1)

这是一个简单的Ruby实现,类似each的方法,它不依赖于任何Ruby的内置迭代器方法:

class List
  def initialize(arr)
    @arr = arr
  end
  def each
    i = 0
    while i < @arr.length
      yield @arr[i]
      i += 1
    end
  end
end

用法:

l = List.new(['a', 'b', 'c'])
l.each {|x| puts x}

输出:

a
b
c

答案 1 :(得分:0)

我可能会迟到这个主题,但我想VALUE数组是一个对象/结构而不是原始值,如int,char等。所以,rb_ary_each方法接收的是对象的指针/引用/ VALUE类型的结构。如果这是真的(我只是在这里猜测我对C的了解)那么块就会在带有retain参数的object / struct中传递。

我还猜测应该存在另一个对象/结构来保存块/ proc / lambda,因此VALUE对象/结构应该保存指向第一个的指针/引用。

如果我错了,请有人纠正我!你的问题与C的工作方式有关,而不是Ruby。