From: Robert Klemme Date: 2011-03-30T21:36:30+09:00 Subject: Re: Getting an Error with local variable On Wed, Mar 30, 2011 at 2:14 PM, Haruka YAGNI wrote: > Robert, thank you for the reply. > > On Wed, Mar 30, 2011 at 7:59 PM, Robert Klemme > wrote: >>>  self.each{|x| x.reach{|y| yield y}} >>> This works but is not elegant. >>> Somebody has an idea? >> >> The approach is broken because the block is not carried through the >> recursion. > > I read your previous post.  I like it. > It is elegant to useblock instead of yield and to add reach method to > Enumerable module. > > I am curious about when my code does not work. > I tested the next script and it printed the same as your code. > > class String >  remove_method(:each) > end This is only needed in 1.8.* btw. $ allruby -e 'String.instance_method "each"' CYGWIN_NT-5.1 padrklemme2 1.7.9(0.237/5/3) 2011-03-29 10:10 i686 Cygwin ======================================== ruby 1.8.7 (2008-08-11 patchlevel 72) [i386-cygwin] ======================================== ruby 1.9.2p180 (2011-02-18 revision 30909) [i386-cygwin] -e:1:in `instance_method': undefined method `each' for class `String' (NameError) from -e:1:in `
' ======================================== jruby 1.6.0 (ruby 1.8.7 patchlevel 330) (2011-03-15 f3b6154) (Java HotSpot(TM) Client VM 1.6.0_24) [Windows XP-x86-java] ======================================== jruby 1.6.0 (ruby 1.9.2 patchlevel 136) (2011-03-15 f3b6154) (Java HotSpot(TM) Client VM 1.6.0_24) [Windows XP-x86-java] NameError: undefined method `each' for class `String' instance_method at org/jruby/RubyModule.java:1957 (root) at -e:1 > class Object >  def reach >   if(self.respond_to?(:each)) >     self.each{|x| x.reach{|y| yield y}} >   else >     yield(self) >   end >  end > end > > [["hoge", "huga"],["foo", "bar"]].reach { |myself| >  print myself > } > > With a nested array, a new block is given to the next 'reach'. > So, I think, if I write this without recursion (of course impossible), > the whole prosess is like >   some_array.each{|x1| x1.each{|x2| x2.each{ .... xn.each {|myself| > print myself} ....}}} > and xn is an unnested array. > > If I misunderstand something, or my program has a bug, please let me know. I'm afraid the bug is in my brain. You are right. I am sorry. I should have taken more time to look at this. That approach does produce awful call stacks though (with multiple levels of nesting the call chain has to go backwards up to the topmost caller to invoke the block initially provided to reach; you can see this by adding "puts caller" to the beginning of the block). I find it more elegant to pass the block down and have it invoked immediately. Apparently you agree with me here. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/