Is there a way to access super from a yield block?
On 15.09.2010 20:59, Gene A. wrote:
Is there a way to access super from a yield block?
What exactly are trying to achieve?
robert
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Am 15.09.2010 20:59, schrieb Gene A.:
Is there a way to access super from a yield block?
None I’m aware of. However, with a heavy bit of metaprogramming,
everything’s possible in Ruby:
class A
def foo
puts “foo in A”
end
end
class B < A
def foo(&block)
puts “foo in B”
if block_given?
super_method = A.instance_method(:foo)
instance_exec(super_method, &block)
end
end
end
x = B.new
x.foo do |super_method|
m = super_method.bind(self)
m.call
end
x.foo
Outputs:
foo in B
foo in A
foo in B
ruby -v: ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux]
Note that I’d NEVER use such a construct in production code. But it’s
fun to try what’s possible in Ruby.
Vale,
Marvin
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAkyRJeMACgkQDYShvwAbcNlfDwCfTBjFhdahiK3gsZWsIP6vmI1w
vaIAn07uvcYdXVjnDw39Az+X7cYCuwQR
=yDm7
-----END PGP SIGNATURE-----
Afternoon,
On Wed, Sep 15, 2010 at 1:12 PM, Gene A. [email protected] wrote:
How about something like this - a little hokey but it works
class A
def x(parm)
puts “Hi from A - #{parm}”
end
end
class B < A
alias :super_x :x
def x(parm)
puts “Hi from B - #{parm}”
do_something { |z| super_x(z) }
end
def do_something
yield “Hello”
end
end
The alias will in essence give you the super method so you can use it
inside
the block.
John
On 09/15/2010 01:12 PM, Gene A. wrote:
def
end
That should work. Can you isolate the problem in a small piece of code
you can post here?
Here’s a working example:
class A
def foo a
“A#foo: #{a}”
end
end
class B < A
def do_something
yield 3
end
def foo
s = do_something {|a| super a}
"B#foo: " + s
end
end
p B.new.foo # ==> “B#foo: A#foo: 3”
What exactly are trying to achieve?
I have class A that derives from class B
A#parse and A#parse! override members of the same name in B
A#parse and A#parse! both call A#do_parse to retrieve arguments from the
command line in a loop. A yield in A#do_parse returns the arguments
(argv). I want to call ‘super argv’ from both A#parse and A#parse! but
super is not set to A#super.
simplified…
class A < B
…
def parse
do_parse {|a| super a}
end
def parse!
do_parse {|a| super a}
def
def do_parse
argv = gets.strip.to_a
return [’-x’] if argv.index ‘-x’
return [’-h’] if argv.empty?
yield argv
end
protected :do_parse
…
end
Gene A. wrote:
What exactly are trying to achieve?
I have class A that derives from class B
A#parse and A#parse! override members of the same name in B
A#parse and A#parse! both call A#do_parse to retrieve arguments from the
command line in a loop. A yield in A#do_parse returns the arguments
(argv). I want to call ‘super argv’ from both A#parse and A#parse! but
super is not set to A#super.
There is no such method as A#super. super means “call the same named
method in the superclass”.
I tried to make your example into a standalone one, but I don’t know if
this is a legitimate demonstration of what you’re trying to do:
----- 8< -----------------------------
class B
def parse(*args)
puts “parse in B(#{args.inspect})”
end
end
class A < B
def parse
do_parse { |a|
puts “Before super”
super a
puts “After super”
}
end
def do_parse
yield [1,2,3]
end
end
A.new.parse
----- 8< -----------------------------
This prints:
Before super
parse in B([[1, 2, 3]])
After super
which is what I expect. I’m using ruby 1.8.7 (2010-01-10 patchlevel 249)
[x86_64-linux]
What do you want it to do instead?
On 15.09.2010 22:12, Gene A. wrote:
What exactly are trying to achieve?
I have class A that derives from class B
A#parse and A#parse! override members of the same name in B
A#parse and A#parse! both call A#do_parse to retrieve arguments from the
command line in a loop. A yield in A#do_parse returns the arguments
(argv). I want to call ‘super argv’ from both A#parse and A#parse! but
super is not set to A#super.
What should “super argv” do? Your description is completele technical
but you don’t tell what the problem is that you are trying to solve
here.
def
Where’s the difference between #parse and #parse!? Also, why do you
want to call the superclass method from the block? This will result in
parsing input twice, since B#parse will also call do_parse. This does
not seem to make much sense
And, btw. reading from stdin from within method #do_parse is not very
modular. It might turn out that you want to read input from a file and
then you need to break this up anyway.
def do_parse
argv = gets.strip.to_a
This will create an Array with a single element. Is this really what
you want?
return ['-x'] if argv.index '-x' return ['-h'] if argv.empty? yield argv
end
protected :do_parse…
end
And: what does the whole picture look like? Why do you want several
classes that somehow must behave differently but apparently share the
same argument parsing code? I would have expected different classes to
have different needs for arguments to be parsed and consequently not
share parsing code. With OptionParser you could do:
class B
def parse(argv)
OptionParser.new do |opts|
fill opts
end.parse argv
end
def parse!(argv)
OptionParser.new do |opts|
fill opts
end.parse! argv
end
protected
def fill(opts)
opts.on ‘-x’ do |…| end
opts.on ‘-y’ do |…| end
end
end
class A < B
def fill(opts)
super
opts.on ‘-z’ do |…| end
end
end
Cheers
robert