【问题标题】:Ruby: Overloading Yield FunctionRuby:重载收益函数
【发布时间】:2013-03-07 16:39:12
【问题描述】:

我在学习 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 方法似乎传递了单个数组元素,而在块内使用一个参数(即,数组)时,它传递了数组本身。 )。

【问题讨论】:

  • @RoneyMichael 如果我错了,请纠正我,但我认为这不是解决方案。 splat 运算符旨在与参数一起使用,而不是与参数一起使用。我的问题是关于我如何构建我的收益语句以及我传递给它们的参数。

标签: ruby yield-keyword


【解决方案1】:

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

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 是什么”逻辑放在对 f 的调用中,g 将一半的逻辑隐藏在自身内部。当您在 Hash 上使用 Enumerable 方法时,差异变得明显的一个地方:

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

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

【讨论】:

  • 非常感谢您的回答。那么有没有一个地方我可以看到ruby如何自动检测和解构(或不解构)这些对象(如数组和哈希)的规则?还是您只是通过反复试验学到的东西,因为它实际上似乎只与数组和哈希有关?另外,对于 g 方法,如果传递给 g 的参数不是数组,yield 函数中的 splat 是否意味着会出现错误?并且只有数组是可分解的吗?这似乎是你所推断的,但我不确定。
  • @user1419674:只有数组会在块参数中自动分解/解构。如果您想了解某些东西如何与Enumerablemap 和朋友的来源)进行交互,那么您必须查看课程的文档。
猜你喜欢
  • 2013-07-03
  • 2021-07-13
  • 1970-01-01
  • 2010-12-21
  • 2019-11-28
  • 2019-04-12
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多