简体   繁体   English

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

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

I'm reading the Pickaxe book on Ruby and I've come across this example:我正在阅读关于 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"

The point of the example is to illustrate that if you prefix the last parameter in a method definition with an ampersand, any associated block is coverted to a Proc object, and that object is assigned to the parameter.该示例的重点是说明,如果您在方法定义中的最后一个参数前加上与号,则任何关联的块都将转换为 Proc object,并且 object 将分配给该参数。

Now, that all makes sense, but I'm stumped on one thing: why do you need to assign name and block to @block in the initialize method?现在,这一切都说得通了,但我被一件事难住了:为什么需要在初始化方法中为@block分配nameblock Why do you need name ?为什么需要name

To me it seems like this should work:对我来说,这似乎应该有效:

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

But, when I try that in irb @block becomes nil and I get an error, NoMethodError (undefined method "call" for nil:NilClass) .但是,当我在 irb 中尝试@block变为 nil 并且出现错误时, NoMethodError (undefined method "call" for nil:NilClass)

I don't understand what name is doing in that @block assignment.我不明白该@block分配中的name在做什么。 It makes sense that you would want to pass "Sales Tax" to @name .您希望将“销售税”传递给@name是有道理的。 But I don't see how "Sales Tax" is being used by the block.但我看不到该街区如何使用“销售税”。

The assignment syntax has nothing to do with blocks.赋值语法与块无关。 Instead, what is happening here is called "parallel assignment".相反,这里发生的事情称为“并行分配”。

With that, you can assign multiple variables on the left from multiple values on the right with one atomic operation.这样,您可以通过一个原子操作从右侧的多个值中分配左侧的多个变量。 From your example, this statement从您的示例中,此语句

@name, @block = name, block

is equivalent to相当于

@name = name
@block = block

In this example, this usage is more of a gimmick (which I'd flag in a code-review).在这个例子中,这种用法更多的是一种噱头(我会在代码审查中标记)。 However, there are some patterns where parallel assignment is very useful.但是,在某些模式中并行分配非常有用。

The most import one is the ability to switch the values of two variables without requiring an intermediate variable:最重要的是能够切换两个变量的值而不需要中间变量:

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

Another option is the ability to deconstruct an array into multiple variables.另一种选择是将数组解构为多个变量的能力。 In the following example, the method returns an array whose elements get assigned to the two variables hello and world .在以下示例中,该方法返回一个数组,其元素被分配给两个变量helloworld

def get_array
  [:hello, :world]
end

hello, world = get_array

The example is using Ruby's parallel assignment operator.该示例使用 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.但我看不到该街区如何使用“销售税”。

The block is not using "Sales Tax".该块未使用“销售税”。 It just computes the tax for the amount passed in get_tax method.它只是计算在get_tax方法中传递的金额的税。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM