There is no such thing as a method inside a method. When you wirte 'def hi',
you actually define the method 'hi' at the same level than the method 'go2'.
So, the later cannot acces the data of the former. However, as they are
defined at the same level, they can share data from the instance variables of
the class they are defined in.
In any case, there is no point to do this.
···
Le vendredi 17 août 2007 17:35, Larry Kluger a écrit :
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?
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.
···
On 8/17/07, Larry Kluger <rubyforum@kluger.com> wrote:
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?
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.
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
···
On 8/17/07, Larry Kluger <rubyforum@kluger.com> wrote:
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?
The general concept involved is that of a closure and it is certainly
possible to define closures in ruby and at some point or another someone
pointed out a way of turning closures into methods I don't remember how
though.
···
On 8/17/07, Larry Kluger <rubyforum@kluger.com> wrote:
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?
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.
···
On 8/17/07, Larry Kluger <rubyforum@kluger.com> wrote:
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?
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 haven't tested the above code so I'm not sure if it really works.
···
On 8/18/07, david karapetyan <dkarapetyan@gmail.com> wrote:
The general concept involved is that of a closure and it is certainly
possible to define closures in ruby and at some point or another someone
pointed out a way of turning closures into methods I don't remember how
though.
On 8/17/07, Larry Kluger <rubyforum@kluger.com> wrote:
>
>
> 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
> --
> Posted via http://www.ruby-forum.com/ .
>
>
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.
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.
On Behalf Of Larry Kluger:
# 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.
this just a stupid example,
irb(main):040:0> def m1
irb(main):041:1> def m2
irb(main):042:2> "x"
irb(main):043:2> end
irb(main):044:1> end
=> nil
irb(main):045:0> m1
=> nil
irb(main):046:0> m2
=> "x"
irb(main):047:0> m1::m2
=> "x"
irb(main):048:0> def m2
irb(main):049:1> "y"
irb(main):050:1> end
=> nil
irb(main):051:0> m2
=> "y"
irb(main):052:0> m1::m2
=> "x"
irb(main):053:0> m1.m2
=> "x"
I haven't tested the above code so I'm not sure if it really works.
On 8/18/07, david karapetyan <dkarapetyan@gmail.com> wrote:
>
> The general concept involved is that of a closure and it is certainly
> possible to define closures in ruby and at some point or another someone
> pointed out a way of turning closures into methods I don't remember how
> though.
>
> On 8/17/07, Larry Kluger <rubyforum@kluger.com> wrote:
> >
> >
> > 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
> > --
> > Posted via http://www.ruby-forum.com/ .
> >
> >
>
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.
···
On 8/18/07, David A. Black <dblack@rubypal.com> wrote:
Hi --
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.
> 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.
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.
···
On 8/17/07, David A. Black <dblack@rubypal.com> wrote:
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.
On 8/17/07, David A. Black <dblack@rubypal.com> wrote:
Hi --
On Sat, 18 Aug 2007, Larry Kluger wrote:
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.
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.