I'm pretty surprised. (I shouldn't be... more on it later)
It happens that what I said in my previous message was _completely_ wrong.
Sorry for that!
···
===
From Programming Ruby 1.9 and 2.0 4th edition - Dave Thomas, Chad
Fowler and Andy Hunt
super
super ‹ ( ‹, param›*‹, *array › ) ›‹block›
Within the body of a method, a call to super acts like a call to the
original method, except that
the search for a method body starts in the superclass of the object
that contained the original
method. If no parameters (and no parentheses) are passed to super, the
original method’s
parameters will be passed; otherwise, the parameters to super will be passed.
===
From Well Grounded Rubyist 2nd Edition - David A. Black
The way super handles arguments is as follows:
■ Called with no argument list (empty or otherwise), super
automatically forwards
the arguments that were passed to the method from which it’s called.
■ Called with an empty argument list—super() —super sends no arguments to
the higher-up method, even if arguments were passed to the current method.
■ Called with specific arguments—super(a,b,c) —super sends exactly those
arguments.
This unusual treatment of arguments exists because the most common
case is the first
one, where you want to bump up to the next-higher method with the same arguments
as those received by the method from which super is being called.
That case is given
the simplest syntax—you just type super . (And because super is a
keyword rather than
a method, it can be engineered to provide this special behavior.)
BUT... (the drummer drums...)
Matz said...
===
The Ruby Programming Language (2008) - David Flanagan and Yukihiro Matsumoto
If you use super as a bare keyword—with no arguments and no
parentheses—then all
of the arguments that were passed to the current method are passed to
the superclass
method. Note, however, that it’s the current values of the method
parameters that are
passed to the superclass method. If the method has modified the values
in its parameter
variables, then the modified values are passed to the invocation of
the superclass
method.
REPEATING: "If the method has modified the values in its parameter
variables, then the modified values are passed to the invocation of
the superclass
method."
That's it.
And... about your block variable question. It seams that &block is
converting the passed block again into the block variable of the super
class. I mean... you didn't passed any args at all. You just passed a
block. The ampersand did the magic of converting the block into the
"block" variable at the son class ("b"). So it does it again at the
superclass ("a"). Just a guess.
Look at these 2 modified versions of your code.
Note that we define #foo on 'c' without any block variable (parameter).
If "d" was passing the block as an argument, it would raise an
ArgumentError because the c's #foo doesn't expect any!
So, I think it's passing as a block, the original block.
c = Class.new do
def foo # without any parameters
puts "block given #{block_given?}"
yield
end
end
d = Class.new(c) do
def foo(&block)
puts "son class: block_id #{block.object_id}"
super
block = -> { puts "Modified Block" }
puts "son class: (after assignment) block_id #{block.object_id}"
super
end
end
d.new.foo{ puts "Block" }
Results:
son class: block_id 70365808831120
block given true
Block
son class: (after assignment) block_id 70365808830900
block given true
Block
c = Class.new do
def foo(&block)
puts "block given #{block_given?}"
puts "superclass: block_id #{block.object_id}"
block.call
end
end
d = Class.new(c) do
def foo(&block)
puts "son class: block_id #{block.object_id}"
super
block = -> { puts "Modified Block" }
puts "son class: (after assignment) block_id #{block.object_id}"
super
end
end
d.new.foo{ puts "Block" }
son class: block_id 70221470263680
block given true
superclass: block_id 70221470263680
Block
son class: (after assignment) block_id 70221470263400
block given true
superclass: block_id 70221470263680
Block
Thanks Arup for bringing this question that I have passed unoticed.
Today I know more Ruby than yesterday!!!
Abinoam Jr.
On Mon, Jan 19, 2015 at 12:41 AM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:
On Sunday, January 18, 2015 11:06:20 PM Abinoam Jr. wrote:
Hi Arup,
Without arguments, super passes the same (actual) "things" that came
as argument to the current method call.
No matter what name you give to it (in this case, "block").
So, making the variable (name of the thing) to point to a different
thing (-> { "b"}) doesn't affect what super knows about the actual
"thing" that was passed as parameter.
Got it?
Best regards and keep rubying,
Abinoam Jr.
Hi Abinoam,
In the first example, you can see the **super** sent the current value of the argument variable **arg**.
In the second example, **super** was sending the previous value of the variable **block**, even if it has been given different value before the **super** call.
-- These 2 observations are contradicting.
--
Regards,
Arup Rakshit
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
--Brian Kernighan