Submitted by eric_mahurin (Fri May 13 17:47:19 UTC 2005)
downto #each - see analysis each_byte each_index each_key each_line each_pair each_value each_with_index reverse_each scan step times upto
.downto => 5 .each => 1091 .each_byte => 19 .each_index => 10 .each_key => 5 .each_line => 4 .each_pair => 5 .each_value => 17 .each_with_index => 23 .reverse_each => 17 .scan => 79 .step => 14 .times => 32 .upto => 28 for => 272 loop => 61 until => 96 while => 375
Of the method loops above, I found (with a script that included multi-line brace matching) only 3 instances of where the current return value is being used:
./optparse.rb: RCSID = %w$Id: optparse.rb,v 1.40.2.4 2004/12/05 10:39:58 nobu Exp $[1..-1].each {|s| s.freeze}.freeze ./optparse.rb: parse(*IO.readlines(filename).each {|s| s.chomp!}) ./rexml/element.rb: prefix = attributes.prefixes.each { |prefix| return "#{prefix}:" if namespace( prefix ) == namespace } || ''
These remaining 2 cases could all be re-written easily and they represent only 0.2% of the "each" calls (and even less if you include "for"). The return values of none of the other methods being discussed was used. Because the return value of "each" is used some, changing its functionality is an optional part of this RCR.
To give an idea of the usefulness, none of the element search methods (i.e. find, include?, index, and variations) would really be needed as they could be written with 1-liners (not much longer and more descriptive):
#enum.find{|o|...} enum.each{|o|break(o) if ...} #enum.include?(x) enum.each{|o|break(true) if o==x} #array.index(x) array.each_with_index{|o,i| break(i) if x==o}
In the above, each_with_index could be used instead of "each" if "each" is not changed (but each_with_index is).
Unfortunately when one of the standard methods doesn't fit a certain search across a group of things, it becomes easiest to use loop/while/until instead of the loop methods (the Ruby way). When you want to find something by iterating over any group of things that are not "Enumerated" (i.e. not "each" or "each_index"), you are even more out of luck since no find-type methods are there.
def <loop-method>(...,&block) ... <while|until|loop do> ... block[...] ... end # "self" was here - remove it # everything else should be the same # just return the natural thing - what the loop would have end
Comments | Current voting | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
RCRchive copyright © David Alan Black, 2003-2005.
Powered by .
I agree with the above comment. It seems like you want to go back to a much more raw, do-it-yourself interface to enumerables, whereas I like having a variety of methods.
In particular, when you say:
you're conjuring up the possibility of a lot of unused index counters, and generally a feeling that there's a workaround for a problem -- but the workaround has really created the problem, in my view.
David Black
The examples above just point out the possibilities this change would offer (a more useful example would be the search for object equality). I think it also promotes better coding style, one of the most important aspects of Ruby. --Michel Martens
I would agree if I was just talking about "each" and "each_with_index". We could easily add a couple more generally useful finding methods to Enumerable (maybe this should be done anyways):
but... what about all of the other each-like routines that Enumerable has no access to. Doing find-like functions across what they iterate is even more of a pain. Take the m.step(n,s) method for example. What use is it for this function to return m? But, having it return nil would be.
Actually, my example search/search_with_index would probably be served with "if found" instead of "unless found.nil?" since comparisons return true/false and not true/nil. With that change, you could emulate find/include?/index with these:
I don't want this to distract from my main proposal though. Only each and each_with_index can take advantage of this. The others listed have no good finding abilities without making this change.
We all agree that good style is good and important.
My problem here is that all I'm seeing are examples that are verbose and "raw" (in the sense of exposing loop logic rather than encapsulating it in appropriately-named methods).
I'm afraid I just don't understand the attraction of this:
as a replacement candidate for this:
Even if this *could* be done with the nil return values, why would one want to do it? How does this enhance Ruby -- stylistically, semantically, expressively, etc.?
Just a thought: Maybe your #search functionality could be had by letting #select take an optional argument specifying the maximum number of elements. If you only wanted one element (at most), then #select could skip the array creation and just return the element or nil.
As for the whole #each thing, I don't see the point. I don't think it's particularly useful for #each (and the other loop methods) to return self, but I don't see why returning nil would be more useful.
Myself, I sometimes do this:
But I don't know if that's relevant, as I honestly don't see the point of this proposal. Voted opposed, just to be difficult.