Default arguments & define_method: MRI - JRuby difference

Hi guys,

I’ve run into a case where MRI and JRuby works differently, and I’m
wondering which is right (my guess is MRI ;-(
It happens when subclassing and dynamically overriding a method with
default arguments.

Trying to distill it, I’ve got the following. The only difference
between B and C: a declared (but unused!) block argument in
define_method.
In one case the default is used, in the other, the actual parameter
passed in the call.
MRI uses the actual param in both cases:

class A
def f(x = :default)
warn “#{self.class} super f(#{x})”
x
end
end

class B < A
define_method :f do |x|
super
end
end

class C < A
define_method :f do # no block arg
super
end
end

B.new.f(:override) #### -> :override
C.new.f(:override) #### -> :default (JRuby), :override (MRI)

So is this a bug in JRuby, MRI, or just a hole in the spec?

Thanks for clarifying this, and BTW, for the great work in general :slight_smile:

Gergo


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

Hi Gergely,

I haven’t looked into the problem deeply, just executed the sample
script in various rubies, and the results are:

  1. JRuby, IronRuby, Rubinius produce “C super f(override)”
  2. MRI 1.8.6/1.8.7 produce “C super f(default)”
  3. MRI 1.9/1.9.1/1.9.2 produce: ': wrong number of arguments (1
    for 0) (ArgumentError)

At first glance, MRI 1.9 behavior is the most correct one. Very
interesting use case you’ve found :slight_smile:

Thanks,
–Vladimir

On Tue, Mar 16, 2010 at 2:23 AM, Gergely N. [email protected] wrote:

In one case the default is used, in the other, the actual parameter

end
Gergo


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

Hi Vladimir,

Thanks for your reply.Sorry for forgetting to specify the Ruby versions
I used.

I haven’t looked into the problem deeply, just executed the sample
script in various rubies, and the results are:

Hmm, interesting, what I found is different:

  1. JRuby, IronRuby, Rubinius produce “C super f(override)”

JRuby trunk (yesterday’s version), gives:
B super f(override)
C super f(default)
Same with --1.9.

  1. MRI 1.8.6/1.8.7 produce “C super f(default)”
    MRI 1.8.7 (2010-01-10 patchlevel 249):
    B super f(override)
    C super f(override)
  1. MRI 1.9/1.9.1/1.9.2 produce: ': wrong number of arguments (1 for 0) (ArgumentError)

MRI 1.9.0 (2008-10-04 revision 19669) gives:
12:in block (1 levels) in <class:B>': implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly. (RuntimeError) from /home/gny/testie.rb:23:in

At first glance, MRI 1.9 behavior is the most correct one.
I completely agree. I would think the behaviour should be matching the
one of the plain old ‘def’ method.

Should I raise a JIRA bug then? I can also add a RubySpec if that
helps…

Thanks,

Gergo

2010/3/16 Vladimir S. [email protected]:

At first glance, MRI 1.9 behavior is the most correct one. Very

It happens when subclassing and dynamically overriding a method with
class A
end

http://xircles.codehaus.org/manage_email


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

Hi Vladimir,

Should I raise a JIRA bug then?
Please, do!
Here you are, http://jira.codehaus.org/browse/JRUBY-4657

Looking at MRI code and ruby-core archives, it seems that block
parameters handling has been changed between 1.8 and 1.9.
Yes, I had heard block arity is taken more seriously in 1.9
(eigenclass.org )
Anyway, it’s good that you brought that up, so I did some more tests:

ruby1.8 -e ‘lambda {|| p “broken”}.call(3)’ #
ArgumentError as expected
jruby -e ‘lambda {|| p “broken”}.call(3)’ #
ArgumentError as expected
ruby1.9 -e ‘lambda {|| p “broken”}.call(3)’ #
ArgumentError as expected
jruby --1.9 -e ‘lambda {|| p “broken”}.call(3)’ # says
“broken” : didn’t check arity at all

ruby1.8 -e ‘lambda { p “OK”}.call(3)’ # OK as
expected
jruby -e ‘lambda { p “OK”}.call(3)’ # OK as
expected
ruby1.9 -e ‘lambda { p “broken”}.call(3)’ #
ArgumentError as expected
jruby --1.9 -e ‘lambda { p “broken”}.call(3)’ # says
“broken”, should be equivalent to ||

This seems to be another bug, ie. jruby 1.9 , which should be
stricter, it’s actually more permissive with block arguments in
general. If this one isn’t reported yet, I’ll do it too.

Gergo

2010/3/16 Vladimir S. [email protected]:

See, for example:

I haven’t looked into the problem deeply, just executed the sample
Thanks,

Trying to distill it, I’ve got the following. The only difference
x
define_method :f do # no block arg

To unsubscribe from this list, please visit:


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

On Tue, Mar 16, 2010 at 1:30 PM, Gergely N. [email protected] wrote:

This seems to be another bug, ie. jruby 1.9 , which should be
stricter, it’s actually more permissive with block arguments in
general. If this one isn’t reported yet, I’ll do it too.

When in doubt, go ahead and file :slight_smile:

  • Charlie

To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

Hi Gergely,

On Tue, Mar 16, 2010 at 10:19 AM, Gergely N. [email protected] wrote:

Hmm, interesting, what I found is different:

At first glance, MRI 1.9 behavior is the most correct one.
I completely agree. I would think the behaviour should be matching the
one of the plain old ‘def’ method.

Looking at MRI code and ruby-core archives, it seems that block
parameters handling has been changed between 1.8 and 1.9.
See, for example:
http://web.archive.org/web/20060613231416/http://rcrchive.net/rcr/show/227

In 1.8, block with no arguments is treated like block with |*unused|,
while in 1.9 is treated as block with || (and such no-args block
reports error when any args are supplied).
Interestingly enough, JRuby doesn’t match any of those. :slight_smile:

Should I raise a JIRA bug then?

Please, do!

I can also add a RubySpec if that helps…

That would be terrific as well! :slight_smile:

Thanks,
–Vladimir

wondering which is right (my guess is MRI ;-(

end
C.new.f(:override) #### → :default (JRuby), :override (MRI)


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email