For loops don't count down

Hello:

I just started learning Ruby. I like it's OOness however I've run across an unusual quirk with the "for loop" that. The "for loop" can count up through a series of numbers, like so:

   for number in (1..5)
     puts number.to_s
   end

which will output the digits 1 through 5. However, the "for loop" does not appear to be able to count down when the range start and end is reversed, like so:

   for number in (5..1)
     puts number.to_s
   end

which outputs nothing. I realize that using "downto" can get me what I want for down counting, like so:

   5.downto(1) do |number|
     puts number.to_s
   end

but I'd like to use the for because it's easier for me to see the start and end of the block (especially when using syntax highlighting editors like RDE).

Can anyone help be understand why the "for loop" can't count down or if there is an alternative "for loop" syntax that I'm missing.

Thank You,

Michael

Hello:

I just started learning Ruby. I like it's OOness however I've run
across an unusual quirk with the "for loop" that. The "for loop" can
count up through a series of numbers, like so:

   for number in (1..5)
     puts number.to_s
   end

for number in [5, 4, 3, 2, 1]
  puts number
end

(oh, note that puts calls .to_s already on its own :wink:

for number in (1..5).to_a.reverse
  puts number
end

either is fine... however, it's not looking very nice... i really
would like to have ranges from top to bottom... not in this
ruby-version available though.

anyway, how is the syntax-highlighting different for for...end vs do...end?
and if you want matching highlighting, you can still do

5.downto(1) { |number|
  puts number
}

that matches the braces, it's the recommended syntax for oneliners though.
like that:

5.downto(1){ |number| puts number }

please note also that for is just syntactic sugar to make the
transition easier for programmers of other languages, what it
essentially does is:

(1..5).to_a.reverse.each do |number|
  puts number
end

hope i could help you with that a little
^ manveru

···

On 2/19/07, Michael Brooks <michael.brooks@shaw.ca> wrote:

which will output the digits 1 through 5. However, the "for loop" does
not appear to be able to count down when the range start and end is
reversed, like so:

   for number in (5..1)
     puts number.to_s
   end

which outputs nothing. I realize that using "downto" can get me what I
want for down counting, like so:

   5.downto(1) do |number|
     puts number.to_s
   end

but I'd like to use the for because it's easier for me to see the start
and end of the block (especially when using syntax highlighting editors
like RDE).

Can anyone help be understand why the "for loop" can't count down or if
there is an alternative "for loop" syntax that I'm missing.

Thank You,

Michael

I realize that using "downto" can get me what I
want for down counting, like so:

   5.downto(1) do |number|
     puts number.to_s
   end

but I'd like to use the for because it's easier for me to see the start
and end of the block (especially when using syntax highlighting editors
like RDE).

Michael

I never use 'for' loops in Ruby. So I can't explain if or why not, etc.
But if you want to use 'for' loops, you could try something like this.

for number in (1..5).to_a.reverse
     puts number.to_s
end

Harry

···

--

"for x in xs" translates internally to "xs.each do |x|", so the
underlying problem is that Range#each only counts upwards.

martin

···

On 2/19/07, Harry <ruby.hardware@gmail.com> wrote:

>
I never use 'for' loops in Ruby. So I can't explain if or why not, etc.

Syntactically, I'd prefer "for number in 5..1" to that monstrous method chain any day of the week.

David Vallner

···

On Mon, 19 Feb 2007 07:28:36 +0100, Michael Fellinger <m.fellinger@gmail.com> wrote:

what it essentially does is:

(1..5).to_a.reverse.each do |number|
  puts number
end

Michael Fellinger wrote:
<snip>

anyway, how is the syntax-highlighting different for for...end vs do...end?
and if you want matching highlighting, you can still do

5.downto(1) { |number|
puts number
}

<snip>

(1..5).to_a.reverse.each do |number|
puts number
end

hope i could help you with that a little
^ manveru

Thank you for the reply. The syntax-highlighter highlights the "for" and the "end" which are both on the left most edge of the block. I like that because it saves me time scanning my code since I don't have to scan to the right to realize it's a block.

I might use the "for number in (1..5).to_a.reverse" variation of the for that Harry suggested below.

I just thought it was strange that the for couldn't do the BASIC style step -1 and the Ruby docs didn't seem to discuss it that I could find.

Thank You!

> what it essentially does is:
>
> (1..5).to_a.reverse.each do |number|
> puts number
> end
>

Syntactically, I'd prefer "for number in 5..1" to that monstrous method
chain any day of the week.

Completely agree, for esthetically reasoning.
But in practice, I am afraid that there is no way to have this David.
As we need 5..1 to be an empty range, or am I blocked?

David Vallner

Robert

···

On 2/19/07, David Vallner <david@vallner.net> wrote:

On Mon, 19 Feb 2007 07:28:36 +0100, Michael Fellinger > <m.fellinger@gmail.com> wrote:

--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important things.
-Anonymous

Harry wrote:

I never use 'for' loops in Ruby. So I can't explain if or why not, etc.
But if you want to use 'for' loops, you could try something like this.

for number in (1..5).to_a.reverse
   puts number.to_s
end

Martin DeMello wrote:

>
I never use 'for' loops in Ruby. So I can't explain if or why not, etc.

"for x in xs" translates internally to "xs.each do |x|", so the
underlying problem is that Range#each only counts upwards.

martin

Thank you Harry and Martin!

Harry, I'll probably try your "to_a.reverse" suggestion for a while (<-no pun intended :)).

Martin, thanks for the explanation! Maybe some day the Range#each will be enhanced to look at the ends of the range and increment or decrement accordingly.

Michael

···

On 2/19/07, Harry <ruby.hardware@gmail.com> wrote:

"Martin DeMello" <martindemello@gmail.com> writes:

>
I never use 'for' loops in Ruby. So I can't explain if or why not, etc.

"for x in xs" translates internally to "xs.each do |x|", so the
underlying problem is that Range#each only counts upwards.

That's not entirely true (there are differences in scope), but the
behavior of #each matters here, yes.

Ranges can't be reversed in general, because there is no backward
equivalent to #succ.

···

On 2/19/07, Harry <ruby.hardware@gmail.com> wrote:

martin

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Numeric#step counts down:

5.step(-1) do |i|
#stuff
end

Aur

···

On 2/19/07, Robert Dober <robert.dober@gmail.com> wrote:

On 2/19/07, David Vallner <david@vallner.net> wrote:
> On Mon, 19 Feb 2007 07:28:36 +0100, Michael Fellinger > > <m.fellinger@gmail.com> wrote:
> > what it essentially does is:
> >
> > (1..5).to_a.reverse.each do |number|
> > puts number
> > end
> >
>
> Syntactically, I'd prefer "for number in 5..1" to that monstrous method
> chain any day of the week.
Completely agree, for esthetically reasoning.
But in practice, I am afraid that there is no way to have this David.
As we need 5..1 to be an empty range, or am I blocked?
>
> David Vallner
>
Robert

--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important things.
-Anonymous

Hi,

···

In message "Re: For loops don't count down" on Mon, 19 Feb 2007 22:27:02 +0900, SonOfLilit <sonoflilit@gmail.com> writes:

Numeric#step counts down:

5.step(-1) do |i|
#stuff
end

5.downto(1) do |i|
end

              matz.

That was already mentioned, but I wanted to show the moer general
solution since it was seeked.

···

On 2/19/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: For loops don't count down" > on Mon, 19 Feb 2007 22:27:02 +0900, SonOfLilit <sonoflilit@gmail.com> writes:

>Numeric#step counts down:
>
>5.step(-1) do |i|
> #stuff
>end

5.downto(1) do |i|
end

                                                        matz.

Yukihiro Matsumoto wrote:

Hi,

>Numeric#step counts down:
>
>5.step(-1) do |i|
> #stuff
>end

5.downto(1) do |i|
end

matz.

Hello Yukihiro:

Thank you for the reply. I tried the step, as shown above, and it doesn't work, it returns a 5, like so:

   irb(main):013:0> 5.step(-1) do |i|
   irb(main):014:0> puts i
   irb(main):015:0> end
   => 5

However, adding the 1 parameter does work, like so:

   irb(main):016:0> 5.step(1,-1) do |i|
   irb(main):017:0> puts i
   irb(main):018:0> end
   5
   4
   3
   2
   1
   => 5

I'm glad that I'm forced to put in the 1 because I wouldn't want it counting down to zero without me realizing it.

However, coming from other languages (e.g. Delphi) I still prefer the for...end syntax because of the more easily recognizable blocks it creates, like so:

   for
     ...
   end

but in time I'm sure I'll get used to seeing number / objects / sets / ranges at the beginning of lines and won't be so hung up on keywords like "for".

Maybe if the Range#each were smart enough to look at the start and end value and count up or down accordingly that would fix things for the (5..1) style syntax. I assume this wouldn't just benefit the "for" but would cause less gotcha's wherever ranges were used.

BTW, thank you for creating such a wonderfully OO language. I looked at Python and it seemed a little inconsistent at times, not to mention all that __<stuff>__, so I was impressed to find such an rich, clean and OO oriented language like Ruby. I was equally impressed to see how much forethought had gone into aspects like sets, iterators, etc. So, please keep up the great work!

Michael

···

In message "Re: For loops don't count down" > on Mon, 19 Feb 2007 22:27:02 +0900, SonOfLilit <sonoflilit@gmail.com> writes:

Is there a necessity for a range such as 5..0 to be empty? It would
otherwise be easy to make iteration work for such cases. This is a
simplified solution that doesn't take into account #exclude_end?

  class Range
    def each
      obj = first
      if first <= last
        while obj <= last
          yield obj
          obj = obj.succ
        end
      else
        while first >= last
          yield obj
          obj = obj.pre
        end
      end
    end
  end

This would of course require that the objects in such a "reverse" range
respond to #pre, or whatever other name would be more suitable.

I'm basically asking if there is a reason why we shouldn't expand the
functionality of Range#each, other than backwards compatibility (not
that that isn't a big consideration.)

Cheers,
Daniel Schierbeck

···

On Mon, 2007-02-19 at 22:38 +0900, Yukihiro Matsumoto wrote:

Hi,

In message "Re: For loops don't count down" > on Mon, 19 Feb 2007 22:27:02 +0900, SonOfLilit <sonoflilit@gmail.com> writes:

>Numeric#step counts down:
>
>5.step(-1) do |i|
> #stuff
>end

5.downto(1) do |i|
end

In math classes, I've seen cases where it's very comfortable that
Sigma (n = b to a) = 0 if b > a.
It was just nice to define something as an empty sum this way
(generalization of solutions).

It's also more according to for(i = a; i < 5; i++) behavior, which is
something very useful. Perhaps we should have syntax for both types.
Or just Range#arrange (awul name) where (a..b).arrange would return
a..a if a<b .

Aur

···

On 2/19/07, Daniel Schierbeck <daniel.schierbeck@gmail.com> wrote:

On Mon, 2007-02-19 at 22:38 +0900, Yukihiro Matsumoto wrote:
> Hi,
>
> In message "Re: For loops don't count down" > > on Mon, 19 Feb 2007 22:27:02 +0900, SonOfLilit <sonoflilit@gmail.com> writes:
>
> >Numeric#step counts down:
> >
> >5.step(-1) do |i|
> > #stuff
> >end
>
> 5.downto(1) do |i|
> end

Is there a necessity for a range such as 5..0 to be empty? It would
otherwise be easy to make iteration work for such cases. This is a
simplified solution that doesn't take into account #exclude_end?

  class Range
    def each
      obj = first
      if first <= last
        while obj <= last
          yield obj
          obj = obj.succ
        end
      else
        while first >= last
          yield obj
          obj = obj.pre
        end
      end
    end
  end

This would of course require that the objects in such a "reverse" range
respond to #pre, or whatever other name would be more suitable.

I'm basically asking if there is a reason why we shouldn't expand the
functionality of Range#each, other than backwards compatibility (not
that that isn't a big consideration.)

Cheers,
Daniel Schierbeck

Hi,

···

In message "Re: For loops don't count down" on Tue, 20 Feb 2007 02:45:27 +0900, Daniel Schierbeck <daniel.schierbeck@gmail.com> writes:

Is there a necessity for a range such as 5..0 to be empty?

5..1 is the easiest case, but what if "abz".."abc" where we couldn't
define reasonable String#pred. Just raise error?

I'd rather swap start and end for each operation, if empty iteration
is not wanted, until we have reverse iteration for generic case.

              matz.

Hi,

>Is there a necessity for a range such as 5..0 to be empty?

5..1 is the easiest case,

No it is not, how could we distinguish between a "reversed" range and
an "empty" range.
but what if "abz".."abc" where we couldn't

define reasonable String#pred. Just raise error?

With all due respect if we have a reasonable String#succ we can define
a reasonable String#pred.

I'd rather swap start and end for each operation, if empty iteration
is not wanted, until we have reverse iteration for generic case.

                                                        matz.

Cheers
Robert

···

On 2/19/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

In message "Re: For loops don't count down" > on Tue, 20 Feb 2007 02:45:27 +0900, Daniel Schierbeck <daniel.schierbeck@gmail.com> writes:

--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important things.
-Anonymous

Hi --

···

On Tue, 20 Feb 2007, Robert Dober wrote:

On 2/19/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: For loops don't count down" >> on Tue, 20 Feb 2007 02:45:27 +0900, Daniel Schierbeck >> <daniel.schierbeck@gmail.com> writes:

>Is there a necessity for a range such as 5..0 to be empty?

5..1 is the easiest case,

No it is not, how could we distinguish between a "reversed" range and
an "empty" range.
but what if "abz".."abc" where we couldn't

define reasonable String#pred. Just raise error?

With all due respect if we have a reasonable String#succ we can define
a reasonable String#pred.

See the thread starting at ruby-talk 38910 for an earlier discussion
of this. It's not easy, and it's arbitrary and of questionable
usefulness. (I don't think ranges need to be any more array-like than
they already are -- possibly less.)

David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Hi --

>> Hi,
>>
>> >Is there a necessity for a range such as 5..0 to be empty?
>>
>> 5..1 is the easiest case,
> No it is not, how could we distinguish between a "reversed" range and
> an "empty" range.
> but what if "abz".."abc" where we couldn't
>> define reasonable String#pred. Just raise error?
> With all due respect if we have a reasonable String#succ we can define
> a reasonable String#pred.

See the thread starting at ruby-talk 38910 for an earlier discussion
of this. It's not easy, and it's arbitrary and of questionable
usefulness. (I don't think ranges need to be any more array-like than
they already are -- possibly less.)

I do not like the lack of symmetry it just feels not right.
I have mixed feelings about String#succ (can be convenient for sure
and very confusing too).
It is no good though to say String#pred will be the same mess, well
than let us remove String#succ too (unfortunately I guess that would
brake too much code.)
I'd like to have a look at the thread though (long time ago, or did I
miss it?) only that the N° is not really good enough for me to find
it.

Sorry if I am the nasty guy again :frowning:

Cheers
Robert

···

On 2/19/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

On Tue, 20 Feb 2007, Robert Dober wrote:
> On 2/19/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:
>> In message "Re: For loops don't count down" > >> on Tue, 20 Feb 2007 02:45:27 +0900, Daniel Schierbeck > >> <daniel.schierbeck@gmail.com> writes:

David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important things.
-Anonymous

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/38910

It's really easy: compose
'http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/&#39; <<
n.to_s

or google for "ruby-talk " << n.to_s

···

On 2/19/07, Robert Dober <robert.dober@gmail.com> wrote:

On 2/19/07, dblack@wobblini.net <dblack@wobblini.net> wrote:
> Hi --
>
> On Tue, 20 Feb 2007, Robert Dober wrote:
>
> > On 2/19/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:
> >> Hi,
> >>
> >> In message "Re: For loops don't count down" > > >> on Tue, 20 Feb 2007 02:45:27 +0900, Daniel Schierbeck > > >> <daniel.schierbeck@gmail.com> writes:
> >>
> >> >Is there a necessity for a range such as 5..0 to be empty?
> >>
> >> 5..1 is the easiest case,
> > No it is not, how could we distinguish between a "reversed" range and
> > an "empty" range.
> > but what if "abz".."abc" where we couldn't
> >> define reasonable String#pred. Just raise error?
> > With all due respect if we have a reasonable String#succ we can define
> > a reasonable String#pred.
>
> See the thread starting at ruby-talk 38910 for an earlier discussion
> of this. It's not easy, and it's arbitrary and of questionable
> usefulness. (I don't think ranges need to be any more array-like than
> they already are -- possibly less.)

I do not like the lack of symmetry it just feels not right.
I have mixed feelings about String#succ (can be convenient for sure
and very confusing too).
It is no good though to say String#pred will be the same mess, well
than let us remove String#succ too (unfortunately I guess that would
brake too much code.)
I'd like to have a look at the thread though (long time ago, or did I
miss it?) only that the N° is not really good enough for me to find
it.

Sorry if I am the nasty guy again :frowning:

Cheers
Robert

>
> David
>
> --
> Q. What is THE Ruby book for Rails developers?
> A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
> (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
> Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
> A. Ruby Power and Light, LLC (http://www.rubypal.com)
>

--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important things.
-Anonymous