下面两个thrice
方法的Ruby语言实现在行为上有什么不同?
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" }
我所说的“行为差异”包括错误处理、性能、工具支持等。
发布于 2009-09-11 10:31:36
如果您忘记传递块,它们会给出不同的错误消息:
> WithYield::thrice
LocalJumpError: no block given
from (irb):3:in `thrice'
from (irb):3:in `times'
from (irb):3:in `thrice'
> WithProcCall::thrice
NoMethodError: undefined method `call' for nil:NilClass
from (irb):9:in `thrice'
from (irb):9:in `times'
from (irb):9:in `thrice'
但是,如果您尝试传递一个“正常”(非块)参数,它们的行为是相同的:
> WithYield::thrice(42)
ArgumentError: wrong number of arguments (1 for 0)
from (irb):19:in `thrice'
> WithProcCall::thrice(42)
ArgumentError: wrong number of arguments (1 for 0)
from (irb):20:in `thrice'
发布于 2016-11-15 18:58:23
我发现结果是不同的,这取决于你是否强制Ruby构造块(例如,一个预先存在的proc)。
require 'benchmark/ips'
puts "Ruby #{RUBY_VERSION} at #{Time.now}"
puts
firstname = 'soundarapandian'
middlename = 'rathinasamy'
lastname = 'arumugam'
def do_call(&block)
block.call
end
def do_yield(&block)
yield
end
def do_yield_without_block
yield
end
existing_block = proc{}
Benchmark.ips do |x|
x.report("block.call") do |i|
buffer = String.new
while (i -= 1) > 0
do_call(&existing_block)
end
end
x.report("yield with block") do |i|
buffer = String.new
while (i -= 1) > 0
do_yield(&existing_block)
end
end
x.report("yield") do |i|
buffer = String.new
while (i -= 1) > 0
do_yield_without_block(&existing_block)
end
end
x.compare!
end
给出了结果:
Ruby 2.3.1 at 2016-11-15 23:55:38 +1300
Warming up --------------------------------------
block.call 266.502k i/100ms
yield with block 269.487k i/100ms
yield 262.597k i/100ms
Calculating -------------------------------------
block.call 8.271M (± 5.4%) i/s - 41.308M in 5.009898s
yield with block 11.754M (± 4.8%) i/s - 58.748M in 5.011017s
yield 16.206M (± 5.6%) i/s - 80.880M in 5.008679s
Comparison:
yield: 16206091.2 i/s
yield with block: 11753521.0 i/s - 1.38x slower
block.call: 8271283.9 i/s - 1.96x slower
如果你把do_call(&existing_block)
改成do_call{}
,你会发现在这两种情况下都要慢5倍。我认为这样做的原因应该是显而易见的(因为Ruby被迫为每个调用构造一个Proc )。
发布于 2011-05-04 12:51:36
顺便说一句,只需使用以下命令将其更新到当前日期:
ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]
在英特尔i7 (1.5年前)上。
user system total real
0.010000 0.000000 0.010000 ( 0.015555)
0.030000 0.000000 0.030000 ( 0.024416)
0.120000 0.000000 0.120000 ( 0.121450)
0.240000 0.000000 0.240000 ( 0.239760)
还是慢了2倍。有意思的。
https://stackoverflow.com/questions/1410160
复制相似问题