On Apr 3, 11:47 ¨Βν¬ ΓομιΒαςτμεττ Όγομιξ®®®ΐηοοημεναιμ®γονχςοτεΊ > On Sat, Apr 3, 2010 at 2:30 PM, Intransition <transf... / gmail.com> wrote: > > Here, I worked on it I came up with: > > Is this the Array#recursively "TODO: Can this be generalized in Enumerable?" :)http://facets.rubyforge.org/apidoc/api/core/classes/Array.html#M000055 Thanks you for pointing this one out. I am working to make these methods more uniform/consistent across all of Facets. There is also similar methods for Pathname and Dir (e.g. Dir#recurse). > Oddly enough, I'd also started wondering about a fully recursive version! > Borrowing ideas from Facets (Array#recursively, Enumerable#traverse) > I came up with the code at the end of this post. It's not as general > as either your code or Robert Klemme's (sort of "orthogonal" to yours) > but it was intended to cope with an element of the array > having an each method but not mixing in Enumerable > > > I am going to add this to Facets, but I have to decide for sure on the > > name. Which is better? #visit #traverse #recurse other ? > > I know they are long names, but because it's a recursive each, why not > #each_recursively (Facets already uses recursively) or #each_recursive > (I prefer the latter - shorter!) and maybe have visit as a short alias? > Or maybe use Robert Klemme's #each_flat, although since this will > apply a recursive each to Ranges (or Files, or anything else using each > which mixes in Enumerable) I'm not sure that flatten (or a derivative) > is fully appropriate? Yes, I was thinking of #recursive_each as well, since that name is also along the lines of #reverse_each. On the other hand #recurse is nice and short and to the point. > I also like Robert Klemme's idea of having a level parameter, > so if Robert is agreeable - and from his Ruby-talk posts he seems to be > a very agreeable person! - maybe include levels, maybe renamed depth? > (I've thought of using level in a more general Find module, and > eventually decided depth was a better word for the concept. I can't > remember why, but I'm sure there must have been very good reasons!) > And maybe cater for "unlimited" depth using depth/levels = nil ? So: > ¨Βμεφεμσ ¦¦ Εξυνεςαβμε ½½> ¨Β®εαγθίζματ¨μεφε챬 ¦β> would become > ¨Β¨΅ μεφεμσ όό μεφεμσ ±© ¦¦ Εξυνεςαβμε ½½> ¨Β®εαγθίζματμεφεμσ ¦¦ μεφεμσ ±¬ ¦β> > A question: should the depth/levels test be levels > 1 or > 0? > Using [ 2..2 ] and "levels > 1": > levels param: 0 #=> 2..2; 1 #=> 2..2; 2 #=> 2; > Using [ 2..2 ] and "levels > 0": > levels param: 0 #=> 2..2; 1 #=> 2; #=> 2; > It seems (maybe?) more logical to have depth/levels arguments: > 0 means don't do any recursive expansion of each; > 1 means do some recursive expansion of each; Yes, I agree, a depth parameter could be useful as well. > ### Intended to cope with an element of an array (or whatever) > ### having an each method but not mixing in Enumerable. > module Enumerable > def visits(&block) > each { |item| Enumerable.visits?(item, &block) } > end > def Enumerable.visits?(obj, &block) > if obj.respond_to?( :each ) then > obj.each { |item| Enumerable.visits?(item, &block) } > else > yield obj > end > end > end Interesting, you could take this a step further. class Object def visits(&block) if respond_to?(:each) each{ |item| item.visits(&block) } else yield(self) end end end Then every object would be "visitable". However, using respond_to? can be dangerous. Consider if I (foolishly) did: class Object def each yield(self) end end The more OOP approach would be: class Object def visits yield(self) end end module Enumerable def visits(&block) each{ |item| item.visits(&block) } end end Then you can override #visits in any object as desired.