Dominik Bathon
2/18/2006 4:16:00 PM
On Sat, 18 Feb 2006 06:49:37 +0100, Joel VanderWerf
<vjoel@path.berkeley.edu> wrote:
> Patrick Ritchie wrote:
>> Hi All,
>>
>> I just setup the following in one of my classes, I'll let the code speak
>> for itself:
>>
>> ["<", "<=", ">", ">=", "==", "<=>"].each do |op|
>> define_method(op) { |comparison| eval "#{self.order} #{op}
>> #{comparison.order}" }
>> end
>>
>> Ruby continues to impress me with it's ability to do so much in so few
>> amazing readable lines of code.
>>
>> Are their any good reasons not to declare my op methods this way? Is
>> their an even more efficient way to achieve the same effect?
>
> It helps to pull the eval out of the define_method:
Or using no eval at all:
> module Order
> attr_reader :order
> def initialize order
> @order = order
> end
> end
>
> class EvalInside
> include Order
> ["<", "<=", ">", ">=", "==", "<=>"].each do |op|
> define_method(op) { |comparison| eval "#{self.order} #{op}
> #{comparison.order}" }
> end
> end
>
> class EvalOutside
> include Order
> ["<", "<=", ">", ">=", "==", "<=>"].each do |op|
> eval "define_method(:#{op}) { |comparison| self.order #{op}
> comparison.order }"
> end
> end
class NoEval
include Order
[:<, :<=, :>, :>=, :==, :<=>].each do |op|
define_method(op) { |comparison| self.order.send(op, comparison.order)
}
end
end
> require 'benchmark'
>
> inside = []
> outside = []
noeval = []
400000.times do |i|
> order = rand(1)
> inside << EvalInside.new(i)
> outside << EvalOutside.new(i)
noeval << NoEval.new(i)
> end
>
> Benchmark.bmbm do |bm|
> bm.report("eval inside") do
> inside.sort
> end
>
> bm.report("eval outside") do
> outside.sort
> end
bm.report("no eval") do
noeval.sort
end
> end
Rehearsal ------------------------------------------------
eval inside 19.310000 0.060000 19.370000 ( 19.500018)
eval outside 1.940000 0.010000 1.950000 ( 1.951829)
no eval 2.600000 0.010000 2.610000 ( 2.626695)
-------------------------------------- total: 23.930000sec
user system total real
eval inside 18.690000 0.080000 18.770000 ( 18.950481)
eval outside 1.920000 0.000000 1.920000 ( 1.940485)
no eval 2.010000 0.000000 2.010000 ( 2.028688)
Dominik