>
> > Hi,
>
> > I've just encountered somehow strange (for me) behavior of nested
> > methods in ruby:
>
> > class A
> > def a
> > def b
> > print "bbb"
> > end
> > end
>
> > def c
> > b
> > end
> > end
>
> > irb(main):013:0> A.new.c
> > bbb=> nil
>
> > class A
> > def b
> > print "BBB"
> > end
> > end
> > irb(main):019:0> A.new.c
> > BBB=> nil
>
> > my first thought was that method/function 'b' would be local to
> > method 'a' in class A (like it would be in Pascal). But this is of
> > course not
> > the case, as the above example shows.
>
> > Is suppose that method 'a' (re)defines method 'b' every time it is
> > called, therefore using nested methods doesn't seem to be a
> > good idea in ruby (better readability but much worse performance, esp.
> > when 'b' isn't a oneliner)
>
> > any comments?
>
> You're right on. I think that nested methods are a bad thing to have
> especially since invocation of an instance method has side effects on
> all instances:
...
>
> #b is defined only after #a has been invoked at least once. I cannot
> think of a scenario where you would want this behavior.
There are dynamic behavior scenarios such as memoize where it could be
used. But such cases are pretty rare. So I agree. Unless inner defs
are local to their outer def, akin to local variables,
Trans, you lost me there on several counts.
What would it mean for an inner def to be local to an inner def.
I get the idea that you mean that, in analogy to local variables we'd see this:
class A
def outer
def inner
...
end
inner # this should work here as should
self.inner # but what about
class.new.inner # should inner be an instance or singleton method?
another rescue "Oops"
method(:inner)
end
private
def another
inner # raises NoMethodError even when called from outer
end
end
A.new.inner.call # And should this work?
So I think the basic meaning is that the inner method would only live
during the execution of the outer method, and would be inaccessible
outside of that stack frame, except maybe if they were returned or
passed.
Of course these all sound like use cases which could easily be handled
with a proc and slighly different syntax.
they really aren't very useful --being little more than a shortcut for
(class << self; self; end).define_method().
Of course this wouldn't work since define_method is private.
Now as Robert K, points out what really happens is that the inner def
is "executed" whenever the outer method is, and other than the timing
it does the same thing as if it were in the class/module context.
Now if one wanted to avoid re-defining such inner methods, one could
write something like:
class A
def outer
unless self.class.instance_methods(false).include?(:inner)
def inner
"inner: a regular instance method"
end
end
unless singleton_methods(false).include?(:my_inner)
def self.my_inner
"my_inner: a singleton instance method"
end
end
end
end
Just anothe way of doing dynamic method definition.
Of course you'd need to do something like carefully remove_method'ing
those inner methods if you wanted to change them.
···
On 6/1/07, Trans <transfire@gmail.com> wrote:
On Jun 1, 3:45 pm, Robert Klemme <shortcut...@googlemail.com> wrote:
> On 01.06.2007 14:36, Artur Merke wrote:
--
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/