如何将块(成为 Proc 对象)传递给 ruby 方法

How to pass a block (which becomes a Proc object) to a ruby method

我正在阅读 Ruby 上的 Pickaxe book,我遇到了这个例子:

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 是有道理的。但我看不到该街区如何使用“销售税”。

该示例使用 Ruby 的并行赋值运算符。

age, salary = 30, 3000   # age=30, salary=3000
age, salary = 30         # age=30, salary=nil
age, salary = [30, 3000] # age=30, salary=3000

But I don't see how "Sales Tax" is being used by the block.

该区块未使用“销售税”。它只是计算在 get_tax 方法中传递的金额的税。

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

这样,您可以通过一个原子操作将右侧的多个值分配给左侧的多个变量。从你的例子来看,这条语句

@name, @block = name, block

相当于

@name = name
@block = block

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

最重要的是无需中间变量即可切换两个变量的值的能力:

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

另一个选项是能够将数组解构为多个变量。在下面的示例中,方法 returns 一个数组,其元素被分配给两个变量 helloworld.

def get_array
  [:hello, :world]
end

hello, world = get_array