0

我在学习 Ruby 时注意到,每种方法的这两种用法都可以工作并产生相同的输出,我想知道 Ruby 是如何实现这一点的(以及如何在我自己的函数中实现这一点):

my_array = [["hello","goodbye"],["picture","perfect"]]

my_array.each do |array|

  puts array[0] + " " + array[1]

end

my_array.each do |first, second|

  puts first + " " + second

end

我的理解是在编写接受代码块的方法的定义时,使用yield方法将参数传递给代码块并调用代码块。但是如何利用 yield 方法,让它根据提供的代码块传递不同的参数呢?在示例情况下,当块内使用两个参数(即,第一个、第二个)时,yield 方法似乎传递了单个数组元素,而在块内使用一个参数(即,数组)时,它传递了数组本身。 )。

4

1 回答 1

1

两者都each没有yield在这里做任何特别的事情,这就是块参数的工作方式。考虑这个简单的例子:

def f(x) yield x end

现在我们可以看到会发生什么:

>> f([1,2]) { |a| puts a.inspect }
[1, 2]
>> f([1,2]) { |a, b| puts "#{a} - #{b}" }
1 - 2
>> f([1,2]) { |a, b, c| puts "#{a} - #{b} - #{c}" }
1 - 2 - 

您会在作业中看到类似的破坏:

a, b = [1, 2]

您也可以使用 splat 显式执行此操作:

a, b = *[1, 2]

或像这样:

def g(x) yield *x end
g([1, 2]) { |a, b| puts "#{a} - #{b}" }

大概该块知道它将给出什么样的东西,因此该块可以很好地解包参数。请注意,该g函数必须知道它的参数是可分解的(即数组),但f不是。f很好地将“是什么样的东西x”逻辑放在对 的调用中fg将一半的逻辑隐藏在自身内部。当您在 Hash 上使用 Enumerable 方法时,差异变得明显的一个地方是:

{ :where => :is, :pancakes => :house? }.map { |k, v| ... }

Enumerable#map不需要知道哈希在键/值两个元素数组中工作,它只是传递东西,让其他人担心细节。

于 2013-03-19T06:46:06.737 回答