C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Part A: We use an iterator with no variable. The number 4 is an object, and we invoke times() to repeat 4 times.
Part B: We add an iteration variable in vertical bars. The variable "i" starts at 0 and is incremented by 1 on each pass through the loop.
Ruby program that uses times
# Part A: use a times-loop.
4.times do
puts "TIMES: 4"
end
# Part B: use a times iterator with an iteration variable.
5.times do |i|
puts "ITERATION: %d" % i
end
Output
TIMES: 4
TIMES: 4
TIMES: 4
TIMES: 4
ITERATION: 0
ITERATION: 1
ITERATION: 2
ITERATION: 3
ITERATION: 4
And: The nested loop uses upto with a variable start and end. An expression, "x + 2," is provided.
Output: The program loops over the indexes 3, 4 and 5. And at each index, it loops over the next two highest numbers.
Ruby program that iterates with upto
# Go up from 3 to 5.
3.upto(5) do |x|
# Go up from x to x + 2.
x.upto(x + 2) do |y|
# Display variable.
print y, " "
end
# End the line.
print "\n"
end
Output
3 4 5
4 5 6
5 6 7
Ruby program that uses upto, short syntax
# Use block syntax.
# ... The do keyword is not required here.
# ... Use format string with puts to write the numbers.
0.upto(3) {|x| puts("Number: %x" % x)}
Output
Number: 0
Number: 1
Number: 2
Number: 3
Tip: The downto iterator is best used for simple loops. The step iterator allows complex or unusual iteration steps—even decrements.
However: As a general rule, using the simplest syntax form necessary for any operation is ideal. If downto is effective, use it.
Ruby program that uses downto, decrements
# Decrement from 5 to 3.
5.downto(3) do |j|
# Display the index.
puts j
end
Output
5
4
3
First argument: This is the ending index. In the first loop, we end at the index 10. In the second, we end at 6.
Second argument: This is the step. The iteration variable is changed by this amount—positive or negative—after each pass.
Ruby program that uses step
# Increment from 0 to 10, by 2 each time.
# ... Name the iteration variable "v".
0.step(10, 2) do |v|
puts v
end
# Decrement from 12 to 6, by -2 each time.
# ... Name the iteration variable "iter".
12.step(6, -2) do |iter|
puts iter
end
Output
0
2
4
6
8
10
12
10
8
6
Thus: A primary reason why we should not always use step is that it introduces further complexity. Using downto, upto or times is simpler.
Tip: Code that is simpler to read is less likely to cause bugs. It can be checked and understood faster.
Program: The 2 iterator invocations here do the same thing. But upto requires less syntax, and may be easier to understand.
Ruby program that compares upto, step
# These 2 iterators do the same thing.
0.upto(4) {|x| puts "UPTO: %d" % x}
0.step(4, 1) {|x| puts "STEP: %d" % x}
Output
UPTO: 0
UPTO: 1
UPTO: 2
UPTO: 3
UPTO: 4
STEP: 0
STEP: 1
STEP: 2
STEP: 3
STEP: 4
String: With a string iterator, we have several ways to loop over the contents of strings.
Each_charRuby program that uses each on array
values = [10, 20, 30]
# Use each on the array of integers.
# ... Print each value with puts in a single-line block.
values.each {|number| puts "VALUE: %d" % number}
Output
VALUE: 10
VALUE: 20
VALUE: 30
Tip: With this style of code, we do not need to manage indexes or increment a variable to loop over a custom sequence or range.
Tip 2: With a custom iterator, we can separate the complexity of a loop into a single, reusable method.
Ruby program that implements iterator, uses yield
def addthree(max)
# Return a sequence incremented by three up to the max.
i = 0
while i <= max
yield i
i += 3
end
end
# Display sequence up to 20.
addthree(20) do |n|
puts n
end
Output
0
3
6
9
12
15
18
Version 1: This version of the code tests the times iterator: it repeats a specific statement 750000 times.
Version 2: Here we use the for-loop with a start index and a max index. It iterates the same number of times as version 1.
Result: I found that the iterator was slightly faster. The results were repeatable. The ordering of the tests did not change my results.
So: When composing Ruby programs, do not avoid using iterators. They may have better performance than loops.
Ruby program that benchmarks iterator, for-loop
count = 750000
n1 = Time.now.usec
# Version 1: use times iterator.
v = 0
count.times do
v += 1
end
puts v
n2 = Time.now.usec
# Version 2: use for-loop.
v = 0
for i in 0..count-1
v += 1
end
puts v
n3 = Time.now.usec
# Compute millisecond timings.
puts ((n2 - n1) / 1000)
puts ((n3 - n2) / 1000)
Output
750000
750000
61 [Time in ms: times() iterator]
64 [Time in ms: for-loop]