On Sat, Apr 3, 2010 at 2:30 PM, Intransition <transfire / 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

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?

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:
     if levels > 1 && Enumerable === x
       x.each_flat(levels - 1, &b)
would become
     if (! levels || levels > 1) && Enumerable === x
       x.each_flat( levels && levels - 1, &b)

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 #=> 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;


### 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