Access super from yield block?

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. :wink:

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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs