为什么这段代码会输出[1, 2, 3, 4, 5]
而不是[2, 3, 4, 5, 6]
?
x = [1, 2, 3, 4, 5]
x.each do |a|
a + 1
end
我在https://ruby-doc.org/core-2.2.0/Array.html#method-i-each查看了each
的来源。这样的东西写在那里。
VALUE
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;
}
有人可以解释一下吗?
答案 0 :(得分:3)
它输出对象,您正在调用each
,因为这是each
的返回值。
如果您只想打印a + 1
,您应该实际输出:
x.each do |a|
puts a + 1
end
或者,如果您所需的结果为[2, 3, 4, 5, 6]
,则需要Enumerable#map
,而不是each
。
x.map { |a| a + 1 }
#=> [2, 3, 4, 5, 6]
答案 1 :(得分:1)
让我通过关键线。
从这一点开始,它就是&#39; ary&#39;在逻辑上等于数组。请注意,较新版本的Ruby(如2.4.0!
)中不存在该行volatile VALUE ary = array;
我跳过了RETURN_SIZED_ENUMERATOR,因为给出了一个块。请参阅include / ruby / intern.h中的源代码。
接下来,我们进入&#39; for&#39;对于'ary&#39;的每个元素阵列。
接下来就是困扰你的线,我相信。首先,它需要来自&#39; ary&#39;数组通过RARRAY_AREF宏。其次,它通过rb_yield将元素的值传递给给定的块(即&#39; a + 1&#39;)。因此,它不存储任何东西。
rb_yield(RARRAY_AREF(ary, i));
由于在rb_yield中没有写入任何内容,因此该函数会返回&#39; ary&#39; [见上文]的数组是输入&#39;数组&#39;。
将其与地图进行比较!&#39;可以帮助你进一步:
static VALUE rb_ary_collect_bang(VALUE ary)
{
long i;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
rb_ary_modify(ary);
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
}
return ary;
}
注意&#39; rb_ary_store&#39; &#39; for&#39;内的函数调用环。这是事情! rb_yield-s就像在每个&#39;变体,但它不会丢弃返回的结果。结果存储在我们[心爱的]&#39; ary的第i个元素中。阵列。