Ruby:Proc#调用vs yield

什么是以下两种实现方式之间Ruby中的行为差异thrice方法?

module WithYield
  def self.thrice
    3.times { yield }      # yield to the implicit block argument
  end
end

module WithProcCall
  def self.thrice(&block)  # & converts implicit block to an explicit, named Proc
    3.times { block.call } # invoke Proc#call
  end
end

WithYield::thrice { puts "Hello world" }
WithProcCall::thrice { puts "Hello world" }

“行为差异”包括错误处理,性能,工具支持等。


我认为第一个实际上是另一个的语法糖。 换句话说,没有行为差异。

第二种形式允许的是将该块“保存”在变量中。 然后可以在其他时间点调用该块 - 回调。


好。 这次我去做了一个快速的基准测试:

require 'benchmark'

class A
  def test
    10.times do
      yield
    end
  end
end

class B
  def test(&block)
    10.times do
      block.call
    end
  end
end

Benchmark.bm do |b|
  b.report do
    a = A.new
    10000.times do
      a.test{ 1 + 1 }
    end
  end

  b.report do
    a = B.new
    10000.times do
      a.test{ 1 + 1 }
    end
  end

  b.report do
    a = A.new
    100000.times do
      a.test{ 1 + 1 }
    end
  end

  b.report do
    a = B.new
    100000.times do
      a.test{ 1 + 1 }
    end
  end

end

结果很有趣:

      user     system      total        real
  0.090000   0.040000   0.130000 (  0.141529)
  0.180000   0.060000   0.240000 (  0.234289)
  0.950000   0.370000   1.320000 (  1.359902)
  1.810000   0.570000   2.380000 (  2.430991)

这表明使用block.call比使用yield要慢两倍。


不同类型的红宝石瓶盖之间的行为差​​异已被广泛记录


这是Ruby 2.x的更新

ruby 2.0.0p247(2013-06-27修订版41674)[x86_64-darwin12.3.0]

我厌倦了手动编写基准测试,所以我创建了一个名为benable的小亚军模块

require 'benchable' # https://gist.github.com/naomik/6012505

class YieldCallProc
  include Benchable

  def initialize
    @count = 10000000    
  end

  def bench_yield
    @count.times { yield }
  end

  def bench_call &block
    @count.times { block.call }
  end

  def bench_proc &block
    @count.times &block
  end

end

YieldCallProc.new.benchmark

产量

                      user     system      total        real
bench_yield       0.930000   0.000000   0.930000 (  0.928682)
bench_call        1.650000   0.000000   1.650000 (  1.652934)
bench_proc        0.570000   0.010000   0.580000 (  0.578605)

我认为这里最令人惊讶的是bench_yieldbench_proc慢。 我希望我多了解一下为什么会发生这种情况。

链接地址: http://www.djcxy.com/p/25821.html

上一篇: Ruby: Proc#call vs yield

下一篇: Ruby's yield feature in relation to computer science