Devious or what? : hacking super : should this work?

Discussion in 'Ruby' started by Jeremy Henty, Jul 15, 2006.

  1. Jeremy Henty

    Jeremy Henty Guest

    I've discovered that an unadorned call to "super" need *not* call the
    parent method with the same arguments!!! If you bind the entire
    argument list to a variable you can modify the list before calling
    "super". Check it out:

    class Show
    def initialize(*args)
    puts args.inspect
    end
    end

    Show.new(1,34,"asd")

    class Show2 < Show
    def initialize(*args)
    puts args.shift
    super
    end
    end

    Show2.new(1,34,"asd")

    ===>

    [1, 34, "asd"]
    1
    [34, "asd"]

    So "args" is bound to the *actual* array of arguments, not just a
    copy. Is this a bug or a feature? Might this behaviour change in
    future?

    Regards,

    Jeremy Henty
    Jeremy Henty, Jul 15, 2006
    #1
    1. Advertising

  2. Jeremy Henty

    Guest

    Hi --

    On Sun, 16 Jul 2006, Jeremy Henty wrote:

    > I've discovered that an unadorned call to "super" need *not* call the
    > parent method with the same arguments!!! If you bind the entire
    > argument list to a variable you can modify the list before calling
    > "super". Check it out:
    >
    > class Show
    > def initialize(*args)
    > puts args.inspect
    > end
    > end
    >
    > Show.new(1,34,"asd")
    >
    > class Show2 < Show
    > def initialize(*args)
    > puts args.shift
    > super
    > end
    > end
    >
    > Show2.new(1,34,"asd")
    >
    > ===>
    >
    > [1, 34, "asd"]
    > 1
    > [34, "asd"]
    >
    > So "args" is bound to the *actual* array of arguments, not just a
    > copy. Is this a bug or a feature? Might this behaviour change in
    > future?


    I assume it's a feature. super should be pretty transparent; for
    example, if an argument is for some reason going to be altered in
    place by the original method, you want that to still happen when you
    call the method that calls super.


    David

    --
    http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
    http://www.manning.com/black => RUBY FOR RAILS (reviewed on
    Slashdot, 7/12/2006!)
    http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
    => me
    , Jul 15, 2006
    #2
    1. Advertising

  3. Jeremy Henty

    Jeremy Henty Guest

    On 2006-07-15, <> wrote:
    > On Sun, 16 Jul 2006, Jeremy Henty wrote:
    >
    >> If you bind the entire argument list to a variable you can modify
    >> the list before calling "super". Check it out:

    >
    > ... super should be pretty transparent; for example, if an argument
    > is for some reason going to be altered in place by the original
    > method, you want that to still happen when you call the method that
    > calls super.


    True, but that's not what surprised me. Given "def foo(*args) ..." I
    always expected the *members* of args to be the arguments of the
    method call (and not copies of them). I did not expect args *itself*
    to be part of the Ruby call stack. I assumed it was just a temporary
    object created on the fly to give me access to the method arguments.
    I thought that nothing else in Ruby had a reference to it, so I
    expected that modifying args itself (rather than its members) would
    have no effect outside of the current scope.

    But I was wrong. It looks like args is the actual array of method
    arguments in the Ruby call stack. Modifying args changes the call
    stack, causing super to supply a different list of objects to the
    parent method.

    Regards,

    Jeremy Henty
    Jeremy Henty, Jul 15, 2006
    #3
  4. On Sat, 15 Jul 2006 23:15:05 +0200, Jeremy Henty <>
    wrote:

    > On 2006-07-15, <> wrote:
    >> On Sun, 16 Jul 2006, Jeremy Henty wrote:
    >>
    >>> If you bind the entire argument list to a variable you can modify
    >>> the list before calling "super". Check it out:

    >>
    >> ... super should be pretty transparent; for example, if an argument
    >> is for some reason going to be altered in place by the original
    >> method, you want that to still happen when you call the method that
    >> calls super.

    >
    > True, but that's not what surprised me. Given "def foo(*args) ..." I
    > always expected the *members* of args to be the arguments of the
    > method call (and not copies of them). I did not expect args *itself*
    > to be part of the Ruby call stack. I assumed it was just a temporary
    > object created on the fly to give me access to the method arguments.


    This definitely is the case for Ruby 1.8 and I can't reproduce your
    example with 1.8.4, only with 1.9. I am not sure why this was changed.

    In 1.8 the arguments are stored in a C array in the FRAME struct and when
    splatting is used a new Ruby array is created every time:

    $ cat super_splat.rb
    class A
    def foo(*a); p a, a.object_id; end
    end

    class B < A
    def foo(*a); p a, a.object_id; a.shift; super; end
    end

    B.new.foo(1,2,3)

    $ ruby super_splat.rb
    [1, 2, 3]
    -604430366
    [1, 2, 3]
    -604430956


    And even in 1.9 it actually is a different Ruby array:

    $ ruby19 super_splat.rb
    [1, 2, 3]
    -604528228
    [2, 3]
    -604528338


    Dominik
    Dominik Bathon, Jul 16, 2006
    #4
  5. Jeremy Henty

    Jeremy Henty Guest

    On 2006-07-16, Dominik Bathon <> wrote:
    > On Sat, 15 Jul 2006 23:15:05 +0200, Jeremy Henty <>
    > wrote:
    >
    >> Given "def foo(*args) ..." I always expected the *members* of args
    >> to be the arguments of the method call (and not copies of them). I
    >> did not expect args *itself* to be part of the Ruby call stack. I
    >> assumed it was just a temporary object created on the fly to give
    >> me access to the method arguments.

    >
    > This definitely is the case for Ruby 1.8 and I can't reproduce your
    > example with 1.8.4, only with 1.9.


    I am running 1.8.5-preview1 . If I downgrade to 1.8.4 I get the
    behaviour I first expected. So my expectations were not that
    ridiculous, which is comforting. And I guess the answer to my
    question "might this behaviour change" is clearly "yes"! (Which means
    I have some code to rewrite, /me sighs.)

    > In 1.8 the arguments are stored in a C array in the FRAME struct and
    > when splatting is used a new Ruby array is created every time:
    >
    > $ cat super_splat.rb
    > class A
    > def foo(*a); p a, a.object_id; end
    > end
    >
    > class B < A
    > def foo(*a); p a, a.object_id; a.shift; super; end
    > end
    >
    > B.new.foo(1,2,3)


    Under 1.8.4 :
    [1, 2, 3]
    -605563672
    [1, 2, 3]
    -605563762

    Under 1.8.5 :
    [1, 2, 3]
    -605295548
    [2, 3]
    -605295638

    Is this an intentional change or a side-effect of something else?

    > And even in 1.9 it actually is a different Ruby array:


    Yes, the array is always a new VALUE (with a different
    (RARRAY(self))->ptr). What's changed is the relation between the C
    array of method arguments that is copied when we call super, and the C
    array that is wrapped by args. It seems that in 1.8.4 the latter is a
    copy of the former, so the call to super gets a copy of the array that
    was originally passed to the current method, even if the contents of
    args have subsequently changed. In 1.8.5 they look to be the same, so
    the call to super gets a copy of the current contents of args.

    Regards,

    Jeremy Henty
    Jeremy Henty, Jul 16, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guest

    super.super.super how?

    Guest, Feb 19, 2005, in forum: Java
    Replies:
    24
    Views:
    10,762
    Darryl Pierce
    Feb 24, 2005
  2. Don@NoSpam

    Devious linkage to enter Web site

    Don@NoSpam, Jul 5, 2004, in forum: HTML
    Replies:
    3
    Views:
    472
    brucie
    Jul 5, 2004
  3. Massimo Soricetti

    Why C/C++ errors are SO obscure/devious??

    Massimo Soricetti, Aug 30, 2005, in forum: C Programming
    Replies:
    24
    Views:
    647
  4. Dan Jacobson

    matching devious non ascii spam strings

    Dan Jacobson, Sep 25, 2004, in forum: Perl Misc
    Replies:
    1
    Views:
    107
    Chris Mattern
    Sep 25, 2004
  5. e.expelliarmus
    Replies:
    1
    Views:
    252
    A. Sinan Unur
    Sep 25, 2007
Loading...

Share This Page