【问题标题】:yield: why can't i write: p test_method { i.upcase }产量:为什么我不能写:p test_method { i.upcase }
【发布时间】:2010-11-28 04:33:11
【问题描述】:
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) }

【问题讨论】:

    标签: ruby yield


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      你打电话的时候

      p test_method {|i| i.upcase}
      

      方法定义中使用的|i|不可见(其范围仅在{}. 特别是您正在构建一个带有单个变量的块,并且要构建该块,您必须指定该变量是什么。请注意,

      p test_method {|j| j.upcase}

      也是有效的。

      【讨论】:

        【解决方案3】:

        在 Ruby 1.9 中,您可以编写:

         p test_method &:upcase
        

        【讨论】:

          【解决方案4】:

          正如 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
          

          【讨论】:

            【解决方案5】:

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

            p test_method &:upcase
            

            所以只需在方法名称前添加 &:

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-03-15
              • 1970-01-01
              • 2012-02-28
              • 1970-01-01
              • 2019-08-01
              • 1970-01-01
              • 2021-04-10
              相关资源
              最近更新 更多