我昨天看到了以下代码(在fruity gem中)
我怎么写这样的东西? (我在下面回答我自己的问题,但随时可以建议编辑或其他方法来解决这个问题:-))
请注意,“slow”,“also_slow”以及下面调用的其他方法不存在:
require 'fruity'
compare do
slow { sleep(0.06) }
also_slow { sleep(0.03); sleep(0.03) }
quick { sleep(0.03) }
quicker { sleep(0.01) }
end
答案 0 :(得分:1)
我知道这与method_missing
有关,但是为了学习的目的,我想写一些类似的东西。
为了实现这一目标,我们需要两件事:
method_missing
的对象,我们将调用该块,因为我们不希望有一个全局method_missing
处理方法(想想slow,also_slow等,在对象)instance_eval
下面是代码:
require 'benchmark'
# the class which instance will be evaluating our missing methods
class BlockEvaluator
attr_accessor :hashy
def initialize
@hashy = {}
end
def method_missing(m, *args, &block)
# collect missing methods' names into hash with the (inner) block of code passed to it
# i.e. { sleep(0.06} }
@hashy[m.to_s] = block if block_given?
end
end
# the method that will be calling the passed block on an instance of BlockEvaluator
def measure_stuff(&block)
be = BlockEvaluator.new
be.instance_eval(&block)
measurements = {}
# get the length of the longest method name (slow, also_slow, etc) in order to pad accordingly
maxlen = be.hashy.keys.map(&:length).max
be.hashy.each do |k,v|
puts "#{k.rjust(maxlen)}#{Benchmark.measure(&v).to_s.chomp}"
end
nil
end
arr = (1..10_000).to_a
# here goes my own
measure_stuff do
zip { 100.times { arr.zip([nil]) } }
product { 100.times { arr.product([nil]) } }
end