Calling outer-scope method of same name

Hi all!

I’m trying to do:

def spleen(a)
end

class Blah
def spleen
spleen(“foo”) # I want this to call the “outer” spleen, above
end
end

…is this possible (using some appropriate syntax?)

I tried ::spleen(“foo”) but was not valid syntax…

Thanks!

Regards,

Bill

Hi –

···

On Fri, 19 Mar 2004, Bill Kelly wrote:

Hi all!

I’m trying to do:

def spleen(a)
end

class Blah
def spleen
spleen(“foo”) # I want this to call the “outer” spleen, above
end
end

…is this possible (using some appropriate syntax?)

I tried ::spleen(“foo”) but was not valid syntax…

Kernel.spleen(“foo”)

David


David A. Black
dblack@wobblini.net

class Blah
def spleen
super(“foo”)
end
end

it’s not as weird as it seems.
see 7.5 in http://www.rubycentral.com/faq/rubyfaqall.html

bill

···

On Fri, Mar 19, 2004 at 07:44:53AM +0900, Bill Kelly wrote:

Hi all!

I’m trying to do:

def spleen(a)
end

class Blah
def spleen
spleen(“foo”) # I want this to call the “outer” spleen, above
end
end

…is this possible (using some appropriate syntax?)

I tried ::spleen(“foo”) but was not valid syntax…

Thanks!

Regards,

Bill

def spleen(a)
end

class Blah
  def spleen
    spleen("foo") # I want this to call the "outer" spleen, above
  end
end

svg% cat b.rb
#!/usr/bin/ruby
def spleen(a)
   puts a
end

class Blah
  def spleen
    super("foo") # I want this to call the "outer" spleen, above
  end
end

Blah.new.spleen
svg%

svg% b.rb
foo
svg%

I tried ::spleen("foo") but was not valid syntax...

Try to forget C++

Guy Decoux

Hi David,

[…]

Kernel.spleen(“foo”)

Here’s what I’m getting:

$ cat test.rb

def spleen(a)
puts “spleen: #{a}”
end

class Blah
def spleen
Kernel.spleen(“foo”)
end
end

Blah.new.spleen

$ ruby -v test.rb
ruby 1.8.1 (2003-12-25) [i686-linux]
test.rb:8:in spleen': private method spleen’ called for Kernel:Module
(NoMethodError)
from test.rb:12

…The “outer” spleen is a private method?

I think I’m missing something… (a brain? :slight_smile:

Confused,

Bill

···

From: “David A. Black” dblack@wobblini.net

Hi –

···

On Fri, 19 Mar 2004, Bill Kelly wrote:

Hi David,

From: “David A. Black” dblack@wobblini.net
[…]

Kernel.spleen(“foo”)

Here’s what I’m getting:

$ cat test.rb

def spleen(a)
puts “spleen: #{a}”
end

class Blah
def spleen
Kernel.spleen(“foo”)
end
end

Blah.new.spleen

$ ruby -v test.rb
ruby 1.8.1 (2003-12-25) [i686-linux]
test.rb:8:in spleen': private method spleen’ called for Kernel:Module
(NoMethodError)
from test.rb:12

…The “outer” spleen is a private method?

I think I’m missing something… (a brain? :slight_smile:

No, my mistake. I tried it in irb, where things apparently are a
little different, and didn’t test or think through the “real”
behavior.

David


David A. Black
dblack@wobblini.net

From: “David A. Black” dblack@wobblini.net
[…]

Kernel.spleen(“foo”)

Here’s what I’m getting:

$ cat test.rb
[snip]

It seems difficult to invoke… I tried this…
but somehow a symbol is expected ?

ruby a.rb
“foo”
a.rb:4:in `public’: nil is not a symbol (TypeError)
from a.rb:4
expand -t2 a.rb
def m
p “foo”
end
public m
class C
def m(scope)
eval(“m”, scope)
end
end
C.m(binding)

···

On Fri, 19 Mar 2004 08:25:45 +0900, Bill Kelly wrote:


Simon Strandgaard

In article 005301c40d41$08e3aaf0$6442a8c0@musicbox,

Hi David,

From: “David A. Black” dblack@wobblini.net
[…]

Kernel.spleen(“foo”)

Shouldn’t it be: Object.spleen(“foo”)

$ cat test.rb

def spleen(a)
puts “spleen: #{a}”
end

class Blah
def spleen
Kernel.spleen(“foo”)

 Object.spleen("foo")

end
end

Blah.new.spleen

Then it should work.

Phil

···

Bill Kelly billk@cts.com wrote:

From: “David A. Black” dblack@wobblini.net
[…]

Kernel.spleen(“foo”)

Here’s what I’m getting:

$ cat test.rb
[snip]

It seems difficult to invoke… I tried this…
but somehow a symbol is expected ?
[snip weird problem]

Ok… now it works

ruby a.rb
“foo”
“foo2”
expand -t2 a.rb
def m(args)
p args
end
class C
def self.m
eval(‘m(“foo”)’, TOPLEVEL_BINDING)
end
def m
eval(‘m(“foo2”)’, TOPLEVEL_BINDING)
end
end
C.m
C.new.m

···

On Fri, 19 Mar 2004 00:31:46 +0100, Simon Strandgaard wrote:

On Fri, 19 Mar 2004 08:25:45 +0900, Bill Kelly wrote:


Simon Strandgaard

Hi –

···

On Fri, 19 Mar 2004, Phil Tomson wrote:

In article 005301c40d41$08e3aaf0$6442a8c0@musicbox,
Bill Kelly billk@cts.com wrote:

Hi David,

From: “David A. Black” dblack@wobblini.net
[…]

Kernel.spleen(“foo”)

Shouldn’t it be: Object.spleen(“foo”)

That won’t change anything; the method will still be private.

David


David A. Black
dblack@wobblini.net

From: “David A. Black” dblack@wobblini.net
[…]

Kernel.spleen(“foo”)

Here’s what I’m getting:

$ cat test.rb
[snip]

It seems difficult to invoke… I tried this…
but somehow a symbol is expected ?

Yup:

public :m

Here’s some samples:

def foo
	puts "outer"
end

class Bar
	def foo
		"inner"
	end
end

Bar.new.foo # => "inner"
foo # => "outer"

class Bar
	def foo
		super
	end
end

Bar.new.foo # => "inner"

Notice that Bar -inherits- foo. When you make an “outer” method, you’re
actually adding it as a private that’s part of Object. That’s why
public :foo
at the top level works the way it does.

···

On Fri, Mar 19, 2004 at 08:39:31AM +0900, Simon Strandgaard wrote:

On Fri, 19 Mar 2004 08:25:45 +0900, Bill Kelly wrote:

ruby a.rb
“foo”
a.rb:4:in `public’: nil is not a symbol (TypeError)
from a.rb:4
expand -t2 a.rb
def m
p “foo”
end
public m
class C
def m(scope)
eval(“m”, scope)
end
end
C.m(binding)


Simon Strandgaard

[…]

Ok… now it works

ruby a.rb
“foo”
“foo2”
expand -t2 a.rb
def m(args)
p args
end
class C
def self.m
eval(‘m(“foo”)’, TOPLEVEL_BINDING)
end
def m
eval(‘m(“foo2”)’, TOPLEVEL_BINDING)
end
end
C.m
C.new.m

Interesting… thanks, Simon!

Regards,

Bill

···

From: “Simon Strandgaard” neoneye@adslhome.dk

Hi –

def foo
puts “outer”
end

class Bar
def foo
“inner”
end
end

Bar.new.foo # => “inner”
foo # => “outer”

class Bar
def foo
super
end
end

Bar.new.foo # => “inner”

That should be “outer”, I think :slight_smile:

My only problem with the ‘super’ approach is that it doesn’t really
execute the top-level version of the method; it executes the next
version up in the method search path, which may or may not be the
top-level version.

def x
puts “Top level”
end

class A
def x
puts “A#x”
end
end

class B < A
def x
super
end
end

B.new.x # => A#x

So it’s not a reliable way of reaching back to the top level.

David

···

On Fri, 19 Mar 2004, Aredridel wrote:


David A. Black
dblack@wobblini.net

From: “Simon Strandgaard” neoneye@adslhome.dk
[…]

class C
def self.m
eval(‘m(“foo”)’, TOPLEVEL_BINDING)
end
def m
eval(‘m(“foo2”)’, TOPLEVEL_BINDING)
end
end

It seems that

Kernel.instance_eval { spleen(“foo”) }

also works!

Regards,

Bill

My only problem with the ‘super’ approach is that it doesn’t really
execute the top-level version of the method; it executes the next
version up in the method search path, which may or may not be the
top-level version.

So it’s not a reliable way of reaching back to the top level.

This works:

def quux(n)
“q#{“u”*n}x”
end

class Foo
def quux(n)
“foo’s q#{“u”*n}x”
end
end

class Bar < Foo
def quux(n)
Object.new.quux(n)
end
end

quux 5 #=> “quuuuux”
Foo.new.quux 5 #=> “foo’s quuuuux”
Bar.new.quux 5 #=> “quuuuux”

Just instantiate an Object, and call the method.

Or, you can rebind the actual method. That would be better if
performance is an issue, I think:

def maybe?
“yes”
end

Foo.new.maybe? #=> “yes”

class Foo
def maybe?
“no”
end
end

Foo.new.maybe? #=> “no”

m=method “maybe?” #=> #<Method: Object#maybe?>

Bar.instance_eval{define_method :maybe?, m}

maybe? #=> “yes”
Foo.new.maybe? #=> “no”
Bar.new.maybe? #=> “yes”

–Mark

···

On Mar 18, 2004, at 6:27 PM, David A. Black wrote:

It’s still better than Kernel.x in the sense that ‘self’ is the right one and
it will work with private instance methods.

The following solves the problem completely IMHO

class Object
def my_call(klass, method, *args, &block)
klass.instance_method(method).bind(self).call(*args, &block)
end
end

def spleen
puts “Object#spleen”
end

class A
def spleen
puts “A#spleen”
end
end

class Blah < A
def spleen
super # uses A’s
puts “now Object’s”
my_call(Object, :spleen) # uses Object’s
end
end

Blah.new.spleen
batsman@tux-chan:/tmp$ ruby dispatch.rb
A#spleen
now Object’s
Object#spleen

One could try to find a better syntax for that, maybe
:Object.call.spleen
or
:Object[:spleen].call
but I’m not so fond of them (implementing this sort of things is fun though :).

···

On Fri, Mar 19, 2004 at 11:27:26AM +0900, David A. Black wrote:

My only problem with the ‘super’ approach is that it doesn’t really
execute the top-level version of the method; it executes the next
version up in the method search path, which may or may not be the
top-level version.

def x
puts “Top level”
end

class A
def x
puts “A#x”
end
end

class B < A
def x
super
end
end

B.new.x # => A#x

So it’s not a reliable way of reaching back to the top level.


Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

I am NOT a kludge! I am a computer!
– tts