【问题标题】:Ruby - Is &prc different than &block?Ruby - &prc 与 &block 不同吗?
【发布时间】:2016-08-17 18:08:41
【问题描述】:

我正在编写一个简单的方法,将num 添加到传递给它的块的返回值中,我注意到 &block 和 &prc 都有效。我知道 proc 是一个对象,可以分配给一个方便的变量。这是唯一的区别吗?在性能、约定或多功能性方面,这两者之间有什么区别吗?使用 &block 代替 &prc 会更好吗?

def adder(num = 1, &block)
  yield + num
end

对比

def adder(num = 1, &prc)
  yield + num
end

【问题讨论】:

    标签: ruby proc


    【解决方案1】:

    这两者有什么区别吗? 性能、惯例或多功能性?

    这两者没有区别,你可以随心所欲地命名它,它只是一个名字。一些开发者称之为&blk 一些&block&b&foo ...

    >> def foo &foo
    >>   yield
    >> end
    => :foo
    >> foo do
    ?>   puts '1'
    >> end
    1
    

    严格来说& 是一个可以应用于任何对象的运算符,它会通过调用to_proc() 将该对象转换为Proc

    >> def bar(&some_proc)
    >>   some_proc
    >> end
    => :bar
    >> p = bar { puts 'Call proc' }
    => #<Proc:0x005601e6d69c80@(irb):4>
    >> p.call
    => Call proc
    >> p.class
    => Proc
    

    只有一件事很重要,名字应该是信息丰富的。

    【讨论】:

    • method 是保留名称,使用该名称定义方法可能会出现问题。
    【解决方案2】:

    在您的方法中添加任何参数,名称在很大程度上是主观的。通常你会看到 &amp;block 只是按照约定使用,但名称本身可以是任何你想要的,只要它是一个有效的变量名。

    在您的示例中,您声明了一个块名称,但实际上并未使用该名称。请记住,任何 Ruby 方法都可以被赋予一个块,没有办法限制这一点,但如果需要,由方法本身来使用该块。该块可以立即或在将来的某个时间被调用零次或多次。将块交给方法会放弃控制,因此请务必仔细阅读任何给定方法的文档。可能会有惊喜。

    如果您需要链接一个块,请使用名称声明它:

    def passes_through(&block)
      [ 1, 2, 3, 4 ].each(&block)
    end
    

    如果你要去街区的yield,这里就不需要了:

    def direct_call
      [ 1, 2, 3, 4 ].each do |n|
        yield n
      end
    end
    

    如果您要保留调用并稍后使用它,这也是命名它的情况:

    def preserved_call(&block)
      @callback = block
    end
    
    def make_callback
      @callback and @callback.call
    end
    

    任何方法都可以检查是否提供了块:

    def tests_for_block
      if (block_given?)
        yield 'value'
      else
        'value'
      end
    end
    

    通过在方法签名中声明块来捕获块的成本很小但可衡量,必须进行大量计算才能正确捕获可能在闭包情况下使用的所有变量。在性能敏感的代码中,您需要避免这种情况。

    您可以动态创建块:

    def captures_conditionally
      if (block_given?)
        @callback = Proc.new
      end
    end
    

    Proc.new 方法将假定控制已提供给该方法的任何块(如果有的话)。

    【讨论】:

      【解决方案3】:

      在您的示例中,&amp;block&amp;prc 之间没有区别,因为在每种情况下,您都只是将要调用的块传递给方法。

      Block 和 proc 的相似之处在于它们都是代码块。

      [1,2,3].each {|x| puts x }
      

      {} 中的所有内容都是块。

      proc 只是一段代码,您可以命名并在以后调用。

      put_element = Proc.new {|x| puts x}
      

      然后你在你的函数中使用 put_element 作为参数。

      【讨论】:

        猜你喜欢
        • 2011-02-28
        • 1970-01-01
        • 2021-05-18
        • 1970-01-01
        • 2017-07-05
        • 2012-09-27
        • 1970-01-01
        • 1970-01-01
        • 2012-07-20
        相关资源
        最近更新 更多