# Define\_method fun

**URL:** <https://www.ruby-forum.com/t/define-method-fun/53954>\
**Category:** Ruby\
**Created:** [February 18, 2006, 4:33am UTC](https://www.ruby-forum.com/t/define-method-fun/53954 "2006-02-18T04:33:02Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![patrickreilly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/b782af/32.png) [@patrickreilly](https://www.ruby-forum.com/u/patrickreilly)\
**Post date:** [February 18, 2006, 4:33am UTC](https://www.ruby-forum.com/t/define-method-fun/53954/1 "2006-02-18T04:33:02Z")

</div>

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?

Cheers!  
Patrick

---

<div class="post-metadata">

**Author:** ![patrickreilly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/b782af/32.png) [@patrickreilly](https://www.ruby-forum.com/u/patrickreilly)\
**Post date:** [February 18, 2006, 6:52am UTC](https://www.ruby-forum.com/t/define-method-fun/53954/2 "2006-02-18T06:52:34Z")

</div>

Patrick R. wrote:

> 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)

---

<div class="post-metadata">

**Author:** ![patrickreilly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/b782af/32.png) [@patrickreilly](https://www.ruby-forum.com/u/patrickreilly)\
**Post date:** [February 18, 2006, 6:55am UTC](https://www.ruby-forum.com/t/define-method-fun/53954/3 "2006-02-18T06:55:38Z")

</div>

Take a look at the Comparable[1] module. It’s a much cleaner, simpler  
way to accomplish what you’re doing.

[1] [module Comparable - RDoc Documentation](http://www.ruby-doc.org/core/classes/Comparable.html)

Gabe

---

<div class="post-metadata">

**Author:** ![patrickreilly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/b782af/32.png) [@patrickreilly](https://www.ruby-forum.com/u/patrickreilly)\
**Post date:** [February 18, 2006, 3:51pm UTC](https://www.ruby-forum.com/t/define-method-fun/53954/4 "2006-02-18T15:51:57Z")

</div>

Wow, that’s impressive, why such huge difference?

Cheers!  
Patrick

---

<div class="post-metadata">

**Author:** ![patrickreilly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/b782af/32.png) [@patrickreilly](https://www.ruby-forum.com/u/patrickreilly)\
**Post date:** [February 18, 2006, 3:55pm UTC](https://www.ruby-forum.com/t/define-method-fun/53954/5 "2006-02-18T15:55:00Z")

</div>

Definitely cleaner in my case, thanks for the tip!

Cheers!  
Patrick

---

<div class="post-metadata">

**Author:** ![patrickreilly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/b782af/32.png) [@patrickreilly](https://www.ruby-forum.com/u/patrickreilly)\
**Post date:** [February 18, 2006, 5:16pm UTC](https://www.ruby-forum.com/t/define-method-fun/53954/6 "2006-02-18T17:16:38Z")

</div>

On Sat, 18 Feb 2006 06:49:37 +0100, Joel VanderWerf  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > 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:

> ```
> define_method(op) { |comparison| eval "#{self.order} #{op}
> 
> ```
> 
> 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

---

<div class="post-metadata">

**Author:** ![patrickreilly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/b782af/32.png) [@patrickreilly](https://www.ruby-forum.com/u/patrickreilly)\
**Post date:** [February 18, 2006, 9:25pm UTC](https://www.ruby-forum.com/t/define-method-fun/53954/7 "2006-02-18T21:25:08Z")

</div>

On Feb 17, 2006, at 7:32 PM, Patrick R. wrote:

> 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?

class YourClass

include Comparable

def \<=\>(other)  
self.order \<=\> other.order  
end

end

–  
Eric H. - removed\_email\_address@domain.invalid - [http://segment7.net](http://segment7.net)  
This implementation is HODEL-HASH-9600 compliant

[http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)

---

<div class="post-metadata">

**Author:** ![patrickreilly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/b782af/32.png) [@patrickreilly](https://www.ruby-forum.com/u/patrickreilly)\
**Post date:** [February 18, 2006, 7:51pm UTC](https://www.ruby-forum.com/t/define-method-fun/53954/8 "2006-02-18T19:51:16Z")

</div>

On Sat, 2006-02-18 at 23:51 +0900, Patrick R. wrote:

> Wow, that’s impressive, why such huge difference?

eval-ing (especially a string) is expensive, basically.

If you move the eval outside the method body, it means you only pay that  
cost once (when defining the method), rather than every time the method  
is run.

-mental

---

<div class="post-metadata">

**Author:** ![patrickreilly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/b782af/32.png) [@patrickreilly](https://www.ruby-forum.com/u/patrickreilly)\
**Post date:** [February 21, 2006, 2:58pm UTC](https://www.ruby-forum.com/t/define-method-fun/53954/9 "2006-02-21T14:58:09Z")

</div>

Ah ah, makes total sense now thanks for the explanation.

Cheers!  
Patrick
