From: Dominik Bathon Date: 2006-02-19T01:15:30+09:00 Subject: Re: define_method fun On Sat, 18 Feb 2006 06:49:37 +0100, Joel VanderWerf 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