Simple object loops and what they return

> > That sure looks ugly. I don't see any advantage of this
over:
> >
> > my_array.each do |item|
> > puts "item"
> > end
> > if my_array.empty?
> > puts "(no items found)"
> > end
>
> *shrug* I personally prefer what I posted over this. (I
tend to use {
> and } for blocks instead of begin/end in my own code
because IMHO it
> visually groups it better, but I used begin/end here since
that seems
> to be the emerging multi-line choice of the community.)
> [snip]

I just wanted to throw in that I'm in the camp of people who
use begin
end when the side effect is important and braces when the
return value
is important. This conveys more meaning on a causual glance.
I.e.

print "100!"
puts (1..100).inject(1) { | r, i |
  r*i
}

(1..100).inject(1) do | r, i |
  puts "#{i}! = #{r = r*i}"
end

inject clearly does what is supposed to. I'm not referring to
it. I'm referring to the following loops that are similar to
plain while/until/loop loops:

enum.each {|o| ...} -> enum or break value
enum.each_with_index {|o,i| ...} -> enum or break value
for o in enum; ... end -> enum or break value
int.times {|i| ...} -> int or break value
int.downto(stop) {|i| ...} -> int or break value
int.upto(stop) {|i| ...} -> int or break value
int.step(stop,step) {|i| ...} -> int or break value

Compare this to the traditional loops:

loop { ... } -> nil or break value
while ...; ... end -> nil or break value
until ...; ... end -> nil or break value
begin ... end while ... -> nil or break value
begin ... end until ... -> nil or break value

I guess many may not know that break can take a value as an
argument and make the broken loop return that. I find this
behavior quite useful except for those loops that return
something other than nil in the no-break case (the object loops
above).

What about the Integer loops above? Anybody using what those
return now - the original int? Maybe I could propose just
those loops.

···

__________________________________
Yahoo! Mail Mobile
Take Yahoo! Mail with you! Check email on your mobile phone.
http://mobile.yahoo.com/learn/mail

Hi --

inject clearly does what is supposed to. I'm not referring to
it. I'm referring to the following loops that are similar to
plain while/until/loop loops:

enum.each {|o| ...} -> enum or break value
enum.each_with_index {|o,i| ...} -> enum or break value
for o in enum; ... end -> enum or break value
int.times {|i| ...} -> int or break value
int.downto(stop) {|i| ...} -> int or break value
int.upto(stop) {|i| ...} -> int or break value
int.step(stop,step) {|i| ...} -> int or break value

Compare this to the traditional loops:

loop { ... } -> nil or break value
while ...; ... end -> nil or break value
until ...; ... end -> nil or break value
begin ... end while ... -> nil or break value
begin ... end until ... -> nil or break value

I guess many may not know that break can take a value as an
argument and make the broken loop return that. I find this
behavior quite useful except for those loops that return
something other than nil in the no-break case (the object loops
above).

What about the Integer loops above? Anybody using what those
return now - the original int? Maybe I could propose just
those loops.

I wonder whether some of the non-consensus about the changes you've
been discussing originates in the difference between loop constructs
per se, and iterators. (loop itself appears to be a method, though
oddly it does not identify itself as an iterator. But an infinite
loop can't really "return" anything anyway.)

So the non-traditional loops you've listed are basically method calls
(including 'for', which I believe is just an 'each' wrapper). I don't
know that this has to be a determinant one way or the other, but I
realize it's something that I'd semi-perceived but not quite put my
finger on that separates these things into two pretty distinct
categories.

David

···

On Thu, 12 May 2005, Eric Mahurin wrote:

--
David A. Black
dblack@wobblini.net

David A. Black wrote:

Hi --

inject clearly does what is supposed to. I'm not referring to
it. I'm referring to the following loops that are similar to
plain while/until/loop loops:

enum.each {|o| ...} -> enum or break value
enum.each_with_index {|o,i| ...} -> enum or break value
for o in enum; ... end -> enum or break value
int.times {|i| ...} -> int or break value
int.downto(stop) {|i| ...} -> int or break value
int.upto(stop) {|i| ...} -> int or break value
int.step(stop,step) {|i| ...} -> int or break value

Compare this to the traditional loops:

loop { ... } -> nil or break value
while ...; ... end -> nil or break value
until ...; ... end -> nil or break value
begin ... end while ... -> nil or break value
begin ... end until ... -> nil or break value

I guess many may not know that break can take a value as an
argument and make the broken loop return that. I find this
behavior quite useful except for those loops that return
something other than nil in the no-break case (the object loops
above).

What about the Integer loops above? Anybody using what those
return now - the original int? Maybe I could propose just
those loops.

I think they normally return the original int value, just like each:

10.times {}

=> 10

10.times { break "foo" }

=> "foo"

I wonder whether some of the non-consensus about the changes you've
been discussing originates in the difference between loop constructs
per se, and iterators. (loop itself appears to be a method, though
oddly it does not identify itself as an iterator. But an infinite
loop can't really "return" anything anyway.)

x = loop do; break "foo"; end

=> "foo"

x

=> "foo"

Sorry, couldn't resist. :-))

So the non-traditional loops you've listed are basically method calls
(including 'for', which I believe is just an 'each' wrapper). I don't
know that this has to be a determinant one way or the other, but I
realize it's something that I'd semi-perceived but not quite put my
finger on that separates these things into two pretty distinct
categories.

Eventually there's most likely a loop construct buried - even in those
method calls... The difference might be smaller than you think: both are
expressions that return something, so the difference between while and
each is not too big.

Kind regards

    robert

···

On Thu, 12 May 2005, Eric Mahurin wrote:

Hi --

David A. Black wrote:

I wonder whether some of the non-consensus about the changes you've
been discussing originates in the difference between loop constructs
per se, and iterators. (loop itself appears to be a method, though
oddly it does not identify itself as an iterator. But an infinite
loop can't really "return" anything anyway.)

x = loop do; break "foo"; end

=> "foo"

x

=> "foo"

Sorry, couldn't resist. :-))

I thought about that one and decided I didn't count it as the loop
"returning" :slight_smile:

So the non-traditional loops you've listed are basically method calls
(including 'for', which I believe is just an 'each' wrapper). I don't
know that this has to be a determinant one way or the other, but I
realize it's something that I'd semi-perceived but not quite put my
finger on that separates these things into two pretty distinct
categories.

Eventually there's most likely a loop construct buried - even in those
method calls... The difference might be smaller than you think: both are
expressions that return something, so the difference between while and
each is not too big.

It's not big conceptually, but while is a keyword and each is a
method. As I said, I don't think that has to determine how they act
with regard to returning values (class is also a keyword, and its
return behavior is very method-like) -- it's just another semantic
factor to keep in view.

David

···

On Thu, 12 May 2005, Robert Klemme wrote:

--
David A. Black
dblack@wobblini.net