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

**URL:** <https://www.ruby-forum.com/t/devious-or-what-hacking-super-should-this-work/98542>\
**Category:** Ruby\
**Created:** [July 15, 2006, 9:27pm UTC](https://www.ruby-forum.com/t/devious-or-what-hacking-super-should-this-work/98542 "2006-07-15T21:27:57Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [July 15, 2006, 9:27pm UTC](https://www.ruby-forum.com/t/devious-or-what-hacking-super-should-this-work/98542/1 "2006-07-15T21:27:57Z")

</div>

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 H.

---

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [July 15, 2006, 10:18pm UTC](https://www.ruby-forum.com/t/devious-or-what-hacking-super-should-this-work/98542/2 "2006-07-15T22:18:59Z")

</div>

Hi –

On Sun, 16 Jul 2006, Jeremy H. wrote:

> ===\>
> 
> [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

---

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [July 15, 2006, 11:19pm UTC](https://www.ruby-forum.com/t/devious-or-what-hacking-super-should-this-work/98542/3 "2006-07-15T23:19:23Z")

</div>

On 2006-07-15, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Sun, 16 Jul 2006, Jeremy H. 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 H.

---

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [July 16, 2006, 12:52pm UTC](https://www.ruby-forum.com/t/devious-or-what-hacking-super-should-this-work/98542/4 "2006-07-16T12:52:40Z")

</div>

On 2006-07-16, Dominik B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

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

> 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 H.

---

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [July 16, 2006, 2:15am UTC](https://www.ruby-forum.com/t/devious-or-what-hacking-super-should-this-work/98542/5 "2006-07-16T02:15:33Z")

</div>

On Sat, 15 Jul 2006 23:15:05 +0200, Jeremy H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 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
