Using define_method isn't the same as defining a method

  • Thread starter Yossef Mendelssohn
  • Start date
Y

Yossef Mendelssohn

I apologize if this has been brought up before. A cursory search
through the archives didn't come up with anything that addressed this
same subject.

I know that creating a Proc (at least a lambda-style Proc) will do
argument checking upon call, and I realize (even though I don't like
it) that those arguments are handled a little oddly:

irb(main):001:0> x = lambda { 'hi' }
=> #<Proc:0x0000ec54@(irb):1>
irb(main):002:0> x.call
=> "hi"
irb(main):003:0> x.call(5)
=> "hi"
irb(main):004:0> x = lambda { |arg| p arg }
=> #<Proc:0x000843a0@(irb):4>
irb(main):005:0> x.call
(irb):4: warning: multiple values for a block parameter (0 for 1)
from (irb):5
nil
=> nil
irb(main):006:0> x.call(5)
5
=> nil
irb(main):007:0> x.call(5,6)
(irb):4: warning: multiple values for a block parameter (2 for 1)
from (irb):7
[5, 6]
=> nil
irb(main):008:0> x = lambda { |arg1, arg2| 'hello' }
=> #<Proc:0x00067674@(irb):8>
irb(main):009:0> x.call
ArgumentError: wrong number of arguments (0 for 2)
from (irb):9
from (irb):9:in `call'
from (irb):9
from :0
irb(main):010:0> x.call(5)
ArgumentError: wrong number of arguments (1 for 2)
from (irb):8
from (irb):10:in `call'
from (irb):10
from :0
irb(main):011:0> x.call(5,6)
=> "hello"
irb(main):012:0> x.call(5,6,7)
ArgumentError: wrong number of arguments (3 for 2)
from (irb):8
from (irb):12:in `call'
from (irb):12
from :0


What I really don't like is how define_method, since it takes a block,
uses this same sort of argument handling. That means

define_method :meth do |arg|
end

is the equivalent of

def meth(*arg)
end

with a warning.

If I want to create a method that takes one argument and acts like a
normal method, what are my choices? Apparently, I get to use only
'def' itself, but that means I need string eval if the method name is
contained in a variable.

Am I wrong? Is there a better way?
 
D

Daniel DeLorme

Yossef said:
What I really don't like is how define_method, since it takes a block,
uses this same sort of argument handling. That means

define_method :meth do |arg|
end

is the equivalent of

def meth(*arg)
end

with a warning.

If I want to create a method that takes one argument and acts like a
normal method, what are my choices? Apparently, I get to use only
'def' itself, but that means I need string eval if the method name is
contained in a variable.

Am I wrong? Is there a better way?

This may not be what you're looking for, but if you need define_method
in order to use a variable from the outer scope, you could do something
like:
some_value = 42
define_method :meth do |*args|
_meth(some_value, *args)
end

..which would bomb if the number of args was incorrect

Daniel
 
G

Giles Bowkett

Sorry, I'm kind of tired right now, plus an irb dump that big is hard
to read - kinda line-noisey - but just one tiny useful note here. At
Ruby East Ezra Z. from EngineYard did a talk on Ruby performance, and
apparently define_method :foo is slower than def foo not just in the
definition but the invocation as well.

Anyway, he also said eval was slow, which was a bummer for me, because
I do like a bit of eval now and then, but other than the slowness, why
not just use eval? Wrestling with that whole args/blocks thing looks
crazy-making and then some.

--
Giles Bowkett

Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com/
 
Y

Yossef Mendelssohn

Sorry, I'm kind of tired right now, plus an irb dump that big is hard
to read - kinda line-noisey - but just one tiny useful note here. At
Ruby East Ezra Z. from EngineYard did a talk on Ruby performance, and
apparently define_method :foo is slower than def foo not just in the
definition but the invocation as well.

Anyway, he also said eval was slow, which was a bummer for me, because
I do like a bit of eval now and then, but other than the slowness, why
not just use eval? Wrestling with that whole args/blocks thing looks
crazy-making and then some.

--
Giles Bowkett

Blog:http://gilesbowkett.blogspot.com
Portfolio:http://www.gilesgoatboy.org
Tumblelog:http://giles.tumblr.com/

It's not something against eval, but more against *string* eval, which
is what I'd need if the method name is held in a variable. And
define_method is RIGHT THERE, so I thought I'd use it. The trouble
comes when you realize it's not the same as def.

You're right about the irb dump. I was just trying to point out the
behavior I was seeing.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,697
Latest member
AugustNabo

Latest Threads

Top