首页 > 解决方案 > 如何将块(成为 Proc 对象)传递给 ruby​​ 方法

问题描述

我正在阅读有关 Ruby 的Pickaxe 书,并且遇到了以下示例:

class TaxCalculator
  def initialize(name, &block)
    @name, @block = name, block
  end

  def get_tax(amount)
    "#@name on #{amount} = #{@block.call(amount)}"
  end
end

tc = TaxCalculator.new ("Sales tax") {|amt| amt * 0.075 }

tc.get_tax(100) # => "Sales tax on 100 = 7.5"
tc.get_tax(250) # => "Sales tax on 250 = 18.75"

该示例的重点是说明,如果您在方法定义中的最后一个参数前面加上一个 & 符号,则任何关联的块都将被转换为 Proc 对象,并且该对象被分配给该参数。

现在,这一切都说得通,但我被一件事难住了:为什么需要在初始化方法中分配nameblock到?@block为什么需要name

对我来说,这似乎应该有效:

 def initialize(name, &block)
   @name, @block = block
 end

但是,当我尝试在 irb 中@block变为 nil 时,我得到一个错误,NoMethodError (undefined method "call" for nil:NilClass).

我不明白name那个任务在做什么@block。您希望将“销售税”传递给@name. 但我看不到该街区如何使用“销售税”。

标签: rubyproc

解决方案


赋值语法与块无关。相反,这里发生的事情称为“并行分配”。

这样,您可以通过一个原子操作从右侧的多个值中分配左侧的多个变量。从您的示例中,此语句

@name, @block = name, block

相当于

@name = name
@block = block

在这个例子中,这种用法更多的是一种噱头(我会在代码审查中标记)。但是,在某些模式中并行分配非常有用。

最重要的是能够切换两个变量的值而不需要中间变量:

a = 1
b = 2
a, b = b, a

另一种选择是将数组解构为多个变量的能力。在以下示例中,该方法返回一个数组,其元素被分配给两个变量helloworld

def get_array
  [:hello, :world]
end

hello, world = get_array

推荐阅读