
-----------------------------------
wtd
Thu Jul 01, 2004 9:01 pm

[Ruby-tut] Doing something... again and again and...
-----------------------------------
Loops in Ruby are where things get really wild, and more than a little excting.  Programmers have grown accustomed to doing a lot of work to get loops in other languages to behave exactly the way they want, with lots of extra variables introduced to get around inflexible syntax.

Ruby changes that by, for the most part, eschewing traditional looping constructs.  Instead the block concept I demonstrated in my previous tutorial, "Method to my madness", allows for endless customization, and this makes for code that's easier to read and understand.

Let's take a simple example.  Print out numbers from zero to nine to standard output.  First I'll demonstrate in C++, and then in Ruby.

#include 

int main()
{
   for (int i = 0; i  9
   puts i
   i += 1
end

This replaces hacks such as:

while (1) { ... }

As with other looping constructs, do and end can be replaced with curly brackets.

i = 0
loop {
   break if i > 9
   puts i
   i += 1
}

However, preferred style is to use "do" and "end" whenever the loop spans multiple lines.

Ruby also has "for".  It's essentially syntactic sugar for the "each" method.  Anything which defines the "each" iterator can be used in a for loop.  As an example, File objects have an each iterator, so the following two examples are effectively identical.  The file is a function I recently wrote to replace strings in C++ std::string objects.

File.open("str_replace.cpp").each do |line|
   puts line
end

for line in File.open("str_replace.cpp")
   puts line
end

And the Tony version.  ;)

for line in File.open("str_replace.cpp") do puts line end

The only difference between these is that variables introduced in the for...in version remain in place after the loop ends.

for x in [1,2,3]
   y = x * 2
   puts y
end

puts y

The above is perfectly valid, since I created the "y" variable in the loop.  However, in the following the "y" is local to the block and doesn't exist in the main program.

[1,2,3].each do |x|
   y = x * 2
   puts y
end

puts y

-----------------------------------
ericfourfour
Sat Dec 16, 2006 3:27 pm


-----------------------------------
I can't get the first example to work:
0.upto 9 { |i| puts i }
I even copy pasted it directly.

I get this output:
irb(main):008:0> 0.upto 9 { |i| puts i }
SyntaxError: compile error
(irb):8: parse error, unexpected '{', expecting $
0.upto 9 { |i| puts i }
          ^
	from (irb):8

-----------------------------------
wtd
Sat Dec 16, 2006 3:40 pm


-----------------------------------
That's actually a mistake on my part.

0.upto(9) { |i| puts i }
