I noticed the other day that methods defined using define_method have very strange behavior when given the wrong number of arguments. For example, here is a class with a bunch of methods defined using define_method:
class Foo define_method :no_args do p "no args" end define_method :one_arg do |one| p one end define_method :two_args do |one, two| p one p two end end
Now, if we call no_args with an argument, it will silently ignore the argument:
>> Foo.new.no_args(1) "no args" => nil
However, if we have a method that expects one argument but receives either none or more than one, we get a warning:
>> Foo.new.one_arg ./foo.rb:6: warning: multiple values for a block parameter (0 for 1) from (irb):3 nil => nil >> Foo.new.one_arg(1,2,3) ./foo.rb:6: warning: multiple values for a block parameter (3 for 1) from (irb):2 [1, 2, 3] => nil
In the second case, it took all three arguments and passed them as an array into the method expecting one argument.
It gets even stranger with a method that expects two arguments. Now, we actually get errors:
>> Foo.new.two_args ArgumentError: wrong number of arguments (0 for 2) from (irb):2:in 'two_args' from (irb):2 >> Foo.new.two_args(1,2,3) ArgumentError: wrong number of arguments (3 for 2) from ./foo.rb:10:in 'two_args' from (irb):3
I’m not sure why a one argument method gives a warning while a two argument method gives an error. Clearly, define_method is very different from using def.
5 Responses to “Strange behavior with define_method and the wrong number of arguments”
Sorry, the comment form is closed at this time.




maybe tell core this
It has nothing to do with the behaviuor of the define_method, but it is because you are passing block to define methods and blocks behaves like this in Ruby 1.8.6 but not in 1.8.7
John Hume, thanks for letting me know. I should have said that I did the above using ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]. I have also seen this behavior with ruby 1.8.5.
Not that this does us any good in the near-term, but define_method methods behave like normal methods with respect to arity in Ruby 1.9.
Hi! Your post sparked my interest and I did some research into this. I have attempted to explain this behaviour here: http://code.lemuria-nation.net/?p=108