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:
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
require 'benchmark'
inside =
outside =
1000000.times do |i|
order = rand(1)
inside << EvalInside.new(i)
outside << EvalOutside.new(i)
end
Benchmark.bmbm do |bm|
bm.report("eval inside") do
inside.sort
end
bm.report("eval outside") do
outside.sort
end
end
Rehearsal ------------------------------------------------
eval inside 17.280000 0.030000 17.310000 ( 18.088599)
eval outside 2.170000 0.010000 2.180000 ( 2.254999)
-------------------------------------- total: 19.490000sec
user system total real
eval inside 17.260000 0.010000 17.270000 ( 17.873053)
eval outside 2.150000 0.010000 2.160000 ( 2.248230)
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407