method access to the enclosing method's locals?

L

Larry Kluger

Hi,

How can a method gain access to the enclosing method's locals?

def go2(arg)
def hi
puts "Hi #{arg}!"
end

a={:h => :hi}
send(a[:h])
end

go2 'Larry' ==>> NameError: undefined local variable or method `arg' for
main:Object

In go2, is there a clean way for the hi method to have access to the
arg local?

Thanks!

Larry
 
O

Olivier Renaud

Le vendredi 17 ao=C3=BBt 2007 17:35, Larry Kluger a =C3=A9crit=C2=A0:
Hi,

How can a method gain access to the enclosing method's locals?

def go2(arg)
def hi
puts "Hi #{arg}!"
end

a=3D{:h =3D> :hi}
send(a[:h])
end

go2 'Larry' =3D=3D>> NameError: undefined local variable or method `arg' = for
main:Object

In go2, is there a clean way for the hi method to have access to the
arg local?

Thanks!

Larry

Hi,

There is no such thing as a method inside a method. When you wirte 'def hi'=
,=20
you actually define the method 'hi' at the same level than the method 'go2'=
=2E=20
So, the later cannot acces the data of the former. However, as they are=20
defined at the same level, they can share data from the instance variables =
of=20
the class they are defined in.

In any case, there is no point to do this.

=2D-=20
Olivier Renaud
 
J

Jano Svitok

Hi,

How can a method gain access to the enclosing method's locals?

def go2(arg)
def hi
puts "Hi #{arg}!"
end

a={:h => :hi}
send(a[:h])
end

go2 'Larry' ==>> NameError: undefined local variable or method `arg' for
main:Object

In go2, is there a clean way for the hi method to have access to the
arg local?

Hi,

you may try something using 1. blocks, 2. passing actual binding, 3.
there was something called binding of caller, but I'm not sure whether
it still works, as it was based on a bug in ruby implementation.

Maybe if you post a bit higher perspective on your problem somebody
would come up with a solution...

J.
 
R

Robert Klemme

Hi,

How can a method gain access to the enclosing method's locals?

def go2(arg)
def hi
puts "Hi #{arg}!"
end

a={:h => :hi}
send(a[:h])
end

go2 'Larry' ==>> NameError: undefined local variable or method `arg' for
main:Object

In go2, is there a clean way for the hi method to have access to the
arg local?

What exactly do you need that for? I am curious because I haven't
stumbled across a problem where I needed this for.

Kind regards

robert
 
D

David A. Black

Hi --

Hi,

How can a method gain access to the enclosing method's locals?

def go2(arg)
def hi
puts "Hi #{arg}!"
end

a={:h => :hi}
send(a[:h])
end

go2 'Larry' ==>> NameError: undefined local variable or method `arg' for
main:Object

In go2, is there a clean way for the hi method to have access to the
arg local?

def always starts a new local scope. If you want to define a method
but in the same scope, you need to use define_method, probably in
conjunction with class_eval or module_eval on the class or module you
want to put it in.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
L

Larry Kluger

Hi Everybody,

Thank you for your help. To keep things dry, my main method uses one of
a number of methods, depending on the value of an argument. A hash is
used as a selector to choose the right child method.

The child methods need some data, I wanted to see how they could gain
access to the locals of the calling method, ie, the main method.

I appreciate the posts; I'll continue to pass the arguments, which is
working fine.

Btw, I find it a bit lacking that the syntax checker allows me to
declare a method inside another method since such things don't exist.
(Per Olivier's helpful post.)

Regards,

Larry
 
D

David A. Black

Hi --

Hi Everybody,

Thank you for your help. To keep things dry, my main method uses one of
a number of methods, depending on the value of an argument. A hash is
used as a selector to choose the right child method.

The child methods need some data, I wanted to see how they could gain
access to the locals of the calling method, ie, the main method.

I appreciate the posts; I'll continue to pass the arguments, which is
working fine.

Btw, I find it a bit lacking that the syntax checker allows me to
declare a method inside another method since such things don't exist.
(Per Olivier's helpful post.)

I wouldn't say it doesn't exist; it's just that the lexically inner
definition isn't scoped to the outer definition. This is relatively
new (1.8.6, if I remember correctly), and made it easier to do
something that was always possible anyway with class_eval +
define_method.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
L

Logan Capaldo

Hi --



I wouldn't say it doesn't exist; it's just that the lexically inner
definition isn't scoped to the outer definition. This is relatively
new (1.8.6, if I remember correctly), and made it easier to do
something that was always possible anyway with class_eval +
define_method.
ISTR def foo; def bar; end; end working in 1.8.4 and possibly even
1.8.2. (I didn't hop aboard the ruby train before 1.8.2 though). I
know I've used def foo; def bar before 1.8.6.
 
L

Logan Capaldo

Hi,

How can a method gain access to the enclosing method's locals?

def go2(arg)
def hi
puts "Hi #{arg}!"
end

a={:h => :hi}
send(a[:h])
end

def initialize
@submeths = {}
end

def dispatch(name, *args)
if @submeths.has_key? name
@submeths[name].call(*args)
else
send(name, *args)
end
end

def submeth(name, &block)
@submeths[name] = block
end

def go2(arg)
# hi = lambda { puts "Hi #{arg}!" }
# personally I would skip the submeths ivar altogether and just do hi.call
# but this is mildly more entertaining
submeth:)hi) { puts "Hi #{arg}" }

a={:h => :hi}
dispatch(a[:h])
end
 
P

Peña, Botp

T24gQmVoYWxmIE9mIExhcnJ5IEtsdWdlcjoNCiMgQnR3LCBJIGZpbmQgaXQgYSBiaXQgbGFja2lu
ZyB0aGF0IHRoZSBzeW50YXggY2hlY2tlciBhbGxvd3MgbWUgdG8gDQojIGRlY2xhcmUgYSBtZXRo
b2QgaW5zaWRlIGFub3RoZXIgbWV0aG9kIHNpbmNlIHN1Y2ggdGhpbmdzIGRvbid0IGV4aXN0LiAN
Cg0KdGhpcyBqdXN0IGEgc3R1cGlkIGV4YW1wbGUsDQoNCmlyYihtYWluKTowNDA6MD4gZGVmIG0x
DQppcmIobWFpbik6MDQxOjE+ICAgZGVmIG0yDQppcmIobWFpbik6MDQyOjI+ICAgICAieCINCmly
YihtYWluKTowNDM6Mj4gICBlbmQNCmlyYihtYWluKTowNDQ6MT4gZW5kDQo9PiBuaWwNCmlyYiht
YWluKTowNDU6MD4gbTENCj0+IG5pbA0KaXJiKG1haW4pOjA0NjowPiBtMg0KPT4gIngiDQppcmIo
bWFpbik6MDQ3OjA+IG0xOjptMg0KPT4gIngiDQppcmIobWFpbik6MDQ4OjA+IGRlZiBtMg0KaXJi
KG1haW4pOjA0OToxPiAgICJ5Ig0KaXJiKG1haW4pOjA1MDoxPiBlbmQNCj0+IG5pbA0KaXJiKG1h
aW4pOjA1MTowPiBtMg0KPT4gInkiDQppcmIobWFpbik6MDUyOjA+IG0xOjptMg0KPT4gIngiDQpp
cmIobWFpbik6MDUzOjA+IG0xLm0yDQo9PiAieCINCg0Ka2luZCByZWdhcmRzIC1ib3RwDQo=
 
D

David A. Black

Hi --

Ok, just ignore all my previous posts. I should have done some more research
before I started typing. This code will actually work.

def go2(arg)
(class << self; self; end).class_eval do
define_method:)hi) do puts "Hi #{arg}" end
end
end

Once you call go2 with some argument it will create the method hi that will
have access to any argument passed to go2. I have to say though all the
redirection with the singleton class makes my head spin a little.

This isn't quite the same as doing an inner def, because you're
defining #hi as a singleton method. If you want to define it as an
instance method of the enclosing class, you would want to do:

self.class.class_eval do ...

As for the head spinning, hopefully someday we'll have this method in
the core (and meanwhile you can write it yourself):

class Object
def singleton_class
class << self; self; end
end
end

Then you can do:

singleton_class.class_eval do ...

which is a little less cluttered. Also, keep in mind that it's not
really redirection; it's just sending messages to objects :) The fact
that you can send messages to Class objects means that you can do what
feels like "meta" stuff in much the same way that you do other things.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
D

David A. Black

Hi --

Maybe you can answer another question. While trying to figure this out I
kept running into scoping issues. The first thing that popped into my head
was

def go2(arg)
clos = proc {puts "Hi #{arg}"}
class << self
define_method:)hi,clos)
end
end

but this didn't work because for some reason when I'm inside the scope of
class << self ... end define_method can't find clos even though it is inside
the enclosing scope. Is there a reason classes don't close over their
enclosing scope because I was thinking just like we can have closures we
could also have closures for classes.

The class keyword always starts a new local scope, but class_eval
doesn't:

x = 1
Object.class_eval { puts x } # 1

class/class_eval is analogous to def/define_method. class and def
start new local scopes; class_eval and define_method don't.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
D

David A. Black

Hi --

ISTR def foo; def bar; end; end working in 1.8.4 and possibly even
1.8.2. (I didn't hop aboard the ruby train before 1.8.2 though). I
know I've used def foo; def bar before 1.8.6.

I think I meant to type 1.8.4, though I'm semi-guessing anyway. I do
seem to remember that it was an intra-1.8 change, rather than as
between 1.6 and 1.8, but I'm not sure.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,979
Messages
2,570,185
Members
46,728
Latest member
FernMcmull

Latest Threads

Top