Normal For Loop

C

Cory Cory

I'm new to Ruby. Is there such thing as a C++ style (and most others)
for loop in Ruby? What I mean by that is:

for( init, while-condition, increment ) { function-here }

I know I can do that with a while loop, but I enjoy the compactness of
the above statement. There are many times where Ruby's for-each loops
just don't do the trick.

Also, is there anything like i++ or do I always have to do i=i+1 ?
 
P

Peter Hickman

Cory said:
I'm new to Ruby. Is there such thing as a C++ style (and most others)
for loop in Ruby? What I mean by that is:

for( init, while-condition, increment ) { function-here }

I know I can do that with a while loop, but I enjoy the compactness of
the above statement. There are many times where Ruby's for-each loops
just don't do the trick.

We would be very interested to see a loop in C that cannot be rewritten
in Ruby. Care to give us an example?
Also, is there anything like i++ or do I always have to do i=i+1 ?
You can use i += 1.
 
J

Jano Svitok

I'm new to Ruby. Is there such thing as a C++ style (and most others)
for loop in Ruby? What I mean by that is:

for( init, while-condition, increment ) { function-here }

I know I can do that with a while loop, but I enjoy the compactness of
the above statement. There are many times where Ruby's for-each loops
just don't do the trick.

There is 5.times {|i| } if the count is known at cycle start.
Then you have array.each {}, and the whole bunch from Enumerable
(each_with_index, select, find, map, inject, ...)
 
E

elof

I'm new to Ruby. Is there such thing as a C++ style (and most others)
for loop in Ruby? What I mean by that is:

for( init, while-condition, increment ) { function-here }

I know I can do that with a while loop, but I enjoy the compactness of
the above statement. There are many times where Ruby's for-each loops
just don't do the trick.

["foo", "bar", "baz"].each_with_index {|elem, i|
puts "#{elem} #{i}"
}


Kristian
 
J

jwmerrill

I'm new to Ruby. Is there such thing as a C++ style (and most others)
for loop in Ruby? What I mean by that is:

for( init, while-condition, increment ) { function-here }

for n in 1..10
puts n
end

It seems more common in ruby to do things like

1.upto(10) {|n| puts n}

or

(1..10).each {|n| puts n}

If you mean that you want your condition and your increment to depend
on things that you won't know about until after the loop has been
running for a while, then yeah, you might have to use a while loop.
This doesn't seem to come up much, though. Perhaps you could post a
specific example.
I know I can do that with a while loop, but I enjoy the compactness of
the above statement. There are many times where Ruby's for-each loops
just don't do the trick.

With a little creativity, not so many, in my experience.
Also, is there anything like i++ or do I always have to do i=i+1 ?

i=i+1 is the way to do it. There is some rationale for this, but I
don't remember what it is.

JM
 
T

Tim Hunter

Jano said:
There is 5.times {|i| } if the count is known at cycle start.
Then you have array.each {}, and the whole bunch from Enumerable
(each_with_index, select, find, map, inject, ...)

Not to mention Numeric#step:

1.step(10, 2) { |i| print i, " " }

And Integer#upto:

5.upto(10) { |i| print i, " " }
 
C

Cory Cory

I understand that all of these for-each style loops are available, but I
don't want to always go through the entire loop, sometimes I want to
stop at some earlier condition.

I tried to do this the other night, but right now I can't find a good
example so here it goes:

a = some_array
minValue = 999999
for(i=0; i<a.length && minValue!=0; i+=1) {
minValue = (5000 - a).abs
}


This isn't the best example. However, there are many times like the
loop above where I want to go through the whole thing, but if I find
exactly what I am looking for, I want to bail out early instead of
wasting that processing time.

Also, I sometimes may want to not actually iterate straight through, but
browse through the array in some more complex order.
 
J

Jano Svitok

i=i+1 is the way to do it. There is some rationale for this, but I
don't remember what it is.

IIRC, the rationale is that variables in ruby are just references to
objects, so you cannot call methods
on variables themselves. You call methods on objects they reference.
That means a call (except assignment)
cannot change the object a variable points to.

i.e. i = 3 that means, variable i points to/references object 3 of class Fixnum.
if there was a call ++, (i++) that would mean the same as 3++. 3++
call can be written so that it returns 4
(actually it's called 3.succ), but there's no way to assign 4 back to
i. It would still point to 3. And because Fixnums are
singletons (there's only one "3" object) they are read only, so
there's no 3.succ!
 
J

jwmerrill

I tried to do this the other night, but right now I can't find a good
example so here it goes:

a = some_array
minValue = 999999
for(i=0; i<a.length && minValue!=0; i+=1) {
minValue = (5000 - a).abs

}


What does this example do exactly? It seems to run until it finds a
value in a that is equal to 5000, and then stop without reporting
anything.

a.detect {|n| 5000 == n}

or

a.any? {|n| 5000 == n}

See, this is actually more concise and readable, I think.
This isn't the best example. However, there are many times like the
loop above where I want to go through the whole thing, but if I find
exactly what I am looking for, I want to bail out early instead of
wasting that processing time.

Also, I sometimes may want to not actually iterate straight through, but
browse through the array in some more complex order.

The point is not that no examples exist, but that they realistically
don't come up very much. Get familiar with the methods in Enumerable,
Array, and Numeric. Each time you want to write a for loop, try and
use one of those instead, and if you get stuck, ask for advice.
You're solution will almost always be more readable, and maybe 1 time
in 100 you'll need to use a while loop.

JM
 
S

Stefano Crocco

Alle Monday 03 March 2008, (e-mail address removed) ha scritto:
I tried to do this the other night, but right now I can't find a good
example so here it goes:

a = some_array
minValue = 999999
for(i=0; i<a.length && minValue!=0; i+=1) {
minValue = (5000 - a).abs

}


What does this example do exactly? It seems to run until it finds a
value in a that is equal to 5000, and then stop without reporting
anything.

a.detect {|n| 5000 == n}

or

a.any? {|n| 5000 == n}

See, this is actually more concise and readable, I think.
This isn't the best example. However, there are many times like the
loop above where I want to go through the whole thing, but if I find
exactly what I am looking for, I want to bail out early instead of
wasting that processing time.

Also, I sometimes may want to not actually iterate straight through, but
browse through the array in some more complex order.

The point is not that no examples exist, but that they realistically
don't come up very much. Get familiar with the methods in Enumerable,
Array, and Numeric. Each time you want to write a for loop, try and
use one of those instead, and if you get stuck, ask for advice.
You're solution will almost always be more readable, and maybe 1 time
in 100 you'll need to use a while loop.

JM


If you want to exit the loop before all iterations are done, you can use
break.

Stefano
 
F

framefritti

Cory Cory ha scritto:
I understand that all of these for-each style loops are available, but I
don't want to always go through the entire loop, sometimes I want to
stop at some earlier condition.

I tried to do this the other night, but right now I can't find a good
example so here it goes:

a = some_array
minValue = 999999
for(i=0; i<a.length && minValue!=0; i+=1) {
minValue = (5000 - a).abs
}


This isn't the best example. However, there are many times like the
loop above where I want to go through the whole thing, but if I find
exactly what I am looking for, I want to bail out early instead of
wasting that processing time.


In this case you can use "break" construct (which I, personally,
love). For example,

minValue = 999999
a.each do |x|
minValue = (5000-x).abs
break if minValue==0
end

(I did not actually try it, but it should work)
Also, I sometimes may want to not actually iterate straight through, but
browse through the array in some more complex order.

In this case I'm afraid that you must resort to a while... (BTW, I
always considered
C-style "for" as a "while" in disguise... ;-)
 
C

Cory Cory

Alright, you people have convinced me. Break seems like a good
solution, I like that you can put a condition after it. The last
submission seems very interested and I'm excited to learn all of these
different array functions.

Anyone know anything about "Rails for PHP Developers" book? I have been
programming in PHP sense I was like 13, it is burned into my head. I
like scripting in Ruby, but I'm still very uncomfortable with Rails
development. Is that book any good?
 
C

Christopher Dicely

I'm new to Ruby. Is there such thing as a C++ style (and most others)
for loop in Ruby? What I mean by that is:

for( init, while-condition, increment ) { function-here }

Simply put, no, Ruby has nothing that works quite like the C-style for loop.
I know I can do that with a while loop, but I enjoy the compactness of
the above statement.

Usually, there is a simpler compact idiom using the iterator methods in the
Enumerable module or specific container classes like Array if you need
something more compact than a while loop.
There are many times where Ruby's for-each loops
just don't do the trick.

The main looping tehcnique in Ruby is using iterator methods. You
could make something like the C-style for loop using them, with the caveat
that all the loop parameters have to be specified as proc objects. It would
be something like (this is code from the top of my head):

module Kernel
def cfor (init, condition, increment)
init.call
while condition.call
yield
increment.call
end
end
end

But, even if proc objects didn't make calling this a little ugly,
you really don't need it: there is generally a better more specific
way of doing things in Ruby.

For instance, in the example you give later in the thread:
a = some_array
minValue = 999999
for(i=0; i<a.length && minValue!=0; i+=1) {
minValue = (5000 - a).abs
}


You seem to want to find the index of the first item in the array
that equals 5000 (which is what the value of i is when you bail
out) or the absolute value of 5000 minus the last item value in
the area (what minValue is if you fail to bail out).

so:

a = some_array
i = a.index(5000) || a.length
minValue = (i<a.length) ? 0 : (5000-a.last).abs

You can probably do something more elegant depending on
what you are doing with the results.
Also, is there anything like i++ or do I always have to do i=i+1 ?

You can do i+=1, i=i.succ, or i=i.next, if you prefer, but Ruby doesn't have
the increment or decrement operators of the C family.
 
S

Saverio Miroddi

I tried to do this the other night, but right now I can't find a good
example so here it goes:

a = some_array
minValue = 999999
for(i=0; i<a.length && minValue!=0; i+=1) {
minValue = (5000 - a).abs
}


This isn't the best example. However, there are many times like the
loop above where I want to go through the whole thing, but if I find
exactly what I am looking for, I want to bail out early instead of
wasting that processing time.

Also, I sometimes may want to not actually iterate straight through, but
browse through the array in some more complex order.


I have a "good" example. In my case I want to iterate a collection,
skipping a variable number of elements based on a given element.
In this case, the C for construct (counter_init, cycle_condition,) would
be useful because I wouldn't have to initialize the counter variable
outside of the scope, and I can increment the counter inside the loop.

The code is something like this:

for ( i = 0; i < elements.size; ) do
if elements[ i ].is_a?( OneType )
do_operation( elements[ i ] );
i += 1;
elsif elements[ i ].is_a?( AnotherType )
sub_elements = []
begin
sub_elements << elements[ i
i += 1;
end while elements[ i ].is_a?( AnotherType )
do_another_operation( sub_elements )
else
...
end
end

This example doesn't pretend to be clever/correct/well constructed, but
is a real-world case where this kind of loop would be useful.
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

I tried to do this the other night, but right now I can't find a good
example so here it goes:

a = some_array
minValue = 999999
for(i=0; i<a.length && minValue!=0; i+=1) {
minValue = (5000 - a).abs
}


This isn't the best example. However, there are many times like the
loop above where I want to go through the whole thing, but if I find
exactly what I am looking for, I want to bail out early instead of
wasting that processing time.

Also, I sometimes may want to not actually iterate straight through, but
browse through the array in some more complex order.


I have a "good" example. In my case I want to iterate a collection,
skipping a variable number of elements based on a given element.
In this case, the C for construct (counter_init, cycle_condition,) would
be useful because I wouldn't have to initialize the counter variable
outside of the scope, and I can increment the counter inside the loop.

The code is something like this:

for ( i = 0; i < elements.size; ) do
if elements[ i ].is_a?( OneType )
do_operation( elements[ i ] );
i += 1;
elsif elements[ i ].is_a?( AnotherType )
sub_elements = []
begin
sub_elements << elements[ i
i += 1;
end while elements[ i ].is_a?( AnotherType )
do_another_operation( sub_elements )
else
...
end
end

This example doesn't pretend to be clever/correct/well constructed, but
is a real-world case where this kind of loop would be useful.


It is probably unwise to put different types of data all in the same array,
but here is my attempt (relies on 1.9 Enumerable method #chunk
http://ruby-doc.org/core/classes/Enumerable.html#M001523)




# these just record what params they received
def do_operation(element)
@do_operation ||= Array.new
@do_operation << element
end

def do_another_operation(elements)
@do_another_operation ||= Array.new
@do_another_operation << elements
end

# sequences of Symbols should be considered a single element
# and Fixnums should be considered a single element
# (the data should probably not be stored like this)
elements = [1,2,:a,:b,3,4,5,9,2,:a,:b]

# chunk the data by its class
chunks = elements.chunk(&:class)
chunks.to_a # => [[Fixnum, [1, 2]], [Symbol, [:a, :b]], [Fixnum, [3, 4, 5,
9, 2]], [Symbol, [:a, :b]]]

# look at each chunk, if they are fixnums, treat them individually
# if they are symbols, treat them as a collection
chunks.each do |klass,chunk|
if Fixnum == klass
chunk.each { |e| do_operation e }
elsif Symbol == klass
do_another_operation chunk
else
# ...
end
end

# What did the methods receive?
@do_operation # => [1, 2, 3, 4, 5, 9, 2]
@do_another_operation # => [[:a, :b], [:a, :b]]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,149
Latest member
Vinay Kumar Nevatia0
Top