0
def test_method
  ["a", "b", "c"].map {|i| yield(i) }
end

如果我这样调用 test_method:

p test_method {|i| i.upcase }
# => ["A", "B", "C"]

为什么我需要块内的 {|i|} 而不是这样说:

p test_method { i.upcase }

我这么认为的原因是因为当在 test_method 中调用 yield 时,我们已经有了一个 {|i|}

  ["a", "b", "c"].map {|i| yield(i) }
4

5 回答 5

3

如果你来自 Groovy 背景,他们有一个隐式迭代器,或者甚至来自 Scala,你可以不用这个 |i| 使用部分函数,​​那么您可能会发现这是一个合乎逻辑的问题,但是,目前您在 Ruby 1.9 甚至在 Rails 中可以做的最好的事情是使用 Symbol#to_block 方法,如 JRL 提到的:

p test_method &:upcase

因此,只需在方法名称前添加& :。

于 2009-09-14T21:08:25.717 回答
2

该块需要一个参数化的值来传递给 upcase 方法。可以这样看:如果省略 |i| 在块中,它无法“捕捉”产生的值(我在 test_method 中)

于 2009-09-14T15:59:36.087 回答
2

在 Ruby 1.9 中,您可以编写:

 p test_method &:upcase
于 2009-09-14T16:04:23.487 回答
2

正如 ennukiller 所说,您必须定义您希望命名从yield语句传回的变量的名称。这与变量的范围有关。您传递给的块内的范围test_method不知道该i变量。您实际上可以随心所欲地调用它。

例如,您可以执行以下操作:

def test_method
  ["a", "b", "c"].map { |i| yield(i) }
end

p test_method { |some_variable_name| some_variable_name.upcase }

仅仅因为测试方法知道它,并不意味着您传递给测试方法的块会知道它。

编辑1:为了提供更多信息,test_method如果它更清楚一点,您可以重新定义如下:

def test_method(&block)
  if not block.nil?
    ["a", "b", "c"].map { |i| yield(i) }
  end
end
于 2009-09-14T16:04:55.220 回答
0

你打电话的时候

p test_method {|i| i.upcase}

|i|方法定义中使用的 不可见(它的范围仅在{}.

p test_method{|j| j.upcase}

也是有效的。

于 2009-09-14T16:04:09.873 回答