无法理解 ruby 中的块和产量

Trouble understanding blocks and yields in ruby

我是 ruby 的初学者,正在学习处理块和产量的教程,特别是演示 Monkey Patching。

这是代码挑战的要求

Write a new new_map method that is called on an instance of the Array class. It should use >the array it's called on as an implicit (self) argument, but otherwise behave identically.

这是我提交的代码

class Array

  def new_map(&block)
    self.map(&block)
  end

  def new_select!(&block)
    self.replace(self.select(&block))
  end

end

这是我必须通过的规格

describe Array do
  describe '#new_map' do
    it "returns an array with updated values" do
     array = [1,2,3,4]
     expect( array.new_map(&:to_s) ).to eq( %w{1 2 3 4} )
     expect( array.new_map{ |e| e + 2 } ).to eq( [3, 4, 5, 6] )
    end

    it "does not call #map" do
     array = [1,2,3,4]
     array.stub(:map) { '' }
     expect( array.new_map(&:to_s) ).to eq( %w{1 2 3 4} )
    end

    it "does not change the original array" do
      array = [1,2,3,4]
      expect( array.new_map(&:to_s) ).to eq( %w{1 2 3 4} )
      expect( array ).to eq([1,2,3,4])
    end
end

我通过了第一次和最后一次测试,但未能通过第二次测试并收到此错误

expected: ["1", "2", "3", "4"]
     got: ""

(compared using ==)

exercise_spec.rb:14:in `block (3 levels) in <top (required)>'

根据规范,我是否可以假设 .map 方法不应该用于此特定挑战?

我什至用这个假设试过了。但它没有通过任何规格。

def new_map(array)
  new_array =[]
  array.each do |i|
    new_array << yield(i)
  end
  new_array
end

更新

我输入了这段代码,它起作用了

def new_map
  new_array = []
  self.each do |i|
    new_array << yield(i)
  end
  new_array
end

但我希望有人能帮助我理解为什么我必须删除参数 (array) 并因此将 array.each 更改为 self.each?

new_map 是数组 class 的一个实例方法,使你的数组​​ == self

[1,2,3].new_map(&:to_s)

self 是 [1,2,3],这是您的 Array 实例

self.each do |i|  

就像

[1,2,3].each do |i|

然后 1,2 和 3 中的每一个都将被传递到块

new_array << yield(i)

But I was hoping someone could help me understand why I had to remove the argument (array) and hence change array.each to self.each?

  1. 背景:你的第一个方法是寻找一个实际上不需要传递的参数,因为数组是调用者本身;换句话说,您正试图将调用者(或 self)作为参数传递给该方法。从技术上讲,您可以做到这一点,但这不是必需的。
  2. 失败原因:但是如果你有一个错误运行之前定义的规范那是因为方法定义被改变了添加该参数。也就是说,您必须像这样调用方法 1:

    new_map数组{块}

虽然参数数组实际上没有被传递,因此给你一个 ArgumentError.