Ryan said:
But you are cheating here by leaving out the "setup code" that allows
you to call ObjectSpace.select.
I don't really see that as cheating since the code is already written
and stored in a reusable lib. EnumerableArgs is not something you'd use
on an existing classes in general, but on something you've created new
--otherwise you'd be redefining #each in a core/standard lib which is
not something you want to do lightly in the first place. It doesn't
really bother ObjectSpace b/c it has no #each method or Enumerable
inclusion, but has an each-like method. So it makes a good example
case.
I would be curious to see other
examples where you use EnumerableArgs, because as Robert says there
aren't many "each" methods that take a parameter. Using ri on my 1.8.2
install, I could only find String#each and IO#each, both of which take
an optional "separator" parameter.
And those are poor parameters to beign with --they have bad side effect
b/c they default to a global var. Not a very robust solution. I hope
Matz will be changing that for 2.0.
I personally don't see many cases
where I would need to override the default, especially when calling
Enumerable methods. Plus since both already include Enumerable, I'm
not sure what kinds of wacky things would happen if you mixed in
EnumerableArgs as well.
If you did include EnumerableArgs there would be no adverse effects
--assumming I it's working as it was designed to. The design goal was
complete transparency. Of course nothing's perfect. I originally wrote
the code for 1.6 so some things have changed. But I did just spend a
couple hours rewritting it to use Enumerator and dynamically generate
the methods based on Enumerable. That way I no longer need to keep it
up-to-date by hand. (Seems a tad slower though suprisingly) So it
should work nearly flawslessly. There are only two caveats. 1) #inject
and #zip can not pass parameters to #each due to their negative arity,
so they work just as they do in Enumerable. And 2) #find (alias
#detect) has been modified to get rid of the 'ifnone' parameter, and
instead made an optional keyword parameter
ifnone=>...), which makes
more sense considering what it is and how rare it's usage is (it only
accepts a proc). So only this last caveat would present a compatabilty
issue if you were for some strange reason to try and make it a complete
drop in replacemet for Enumerable.
Now what kind of use real might it have besides ObjectSpace? Simply
imagine any class that might have multipe each methods:
class House
include EnumerableArgs
def each_bedroom ...
def each_closet ...
def each_room ...
def each_hallway ...
def each(which=:room, &blk)
send("each_#{which}", &blk)
end
end
h = House.new
h.select
bathroom) { |b| ... }
T.