Control Flow
## Learning Objectives
- Use conditional statements (if, unless, case)
- Work with loops (while, until, for)
- Master iterators and Enumerable
- Understand loop control (break, next, redo)
## If-Unless
### If Statement
```ruby
temperature = 25
if temperature > 30
puts "Hot"
elsif temperature > 20
puts "Nice"
else
puts "Cold"
end
```
### Unless Statement
```ruby
# unless is opposite of if (executes when condition is false)
unless temperature > 30
puts "Not hot"
end
# Equivalent to:
if !(temperature > 30)
puts "Not hot"
end
```
### Modifier Form
```ruby
puts "Valid" if age >= 18
puts "Minor" unless age >= 18
# Multi-line modifier
if score > 90
grade = "A"
end
# Same as:
grade = "A" if score > 90
```
### Ternary Operator
```ruby
age = 20
status = age >= 18 ? "adult" : "minor"
puts status # "adult"
```
### Combined Comparison
```ruby
# && - both must be true
if age >= 18 && has_license
puts "Can drive"
end
# || - either can be true
if is_member || has_ticket
puts "Allowed entry"
end
```
## Case-When
### Basic Syntax
```ruby
grade = case score
when 90..100
"A"
when 80..89
"B"
when 70..79
"C"
when 60..69
"D"
else
"F"
end
```
### One-liner Form
```ruby
grade = case score
when 90..100 then "A"
when 80..89 then "B"
when 70..79 then "C"
else "F"
end
```
### Case with Multiple Values
```ruby
day = case weekday
when "Saturday", "Sunday"
"Weekend"
when "Monday", "Wednesday", "Friday"
"MWF Classes"
else
"Other Day"
end
```
### Case with No Argument
```ruby
name = "Alice"
greeting = case
when name.nil?
"Who are you?"
when name.empty?
"Hello, stranger"
else
"Hello, #{name}"
end
```
## Loops
### While Loop
```ruby
count = 1
while count <= 5
puts count
count += 1
end
```
### Until Loop
```ruby
# until executes while condition is false
count = 1
until count > 5
puts count
count += 1
end
```
### For Loop
```ruby
# Iterate over range
for i in 1..5
puts i
end
# Iterate over array
fruits = ["apple", "banana", "cherry"]
for fruit in fruits
puts fruit
end
```
### Loop as Iterator
```ruby
# 5.times do
5.times { puts "Hello" }
# upto
1.upto(5) { |n| puts n }
# downto
5.downto(1) { |n| puts n }
# step
0.step(10, 2) { |n| puts n } # 0, 2, 4, 6, 8, 10
```
## Iterators
### Times Iterator
```ruby
5.times do |i|
puts "Iteration #{i}"
end
# Without block variable
3.times { puts "Hello" }
```
### Each Iterator
```ruby
# Array
[1, 2, 3].each { |n| puts n }
# Hash
{ a: 1, b: 2 }.each do |key, value|
puts "#{key}: #{value}"
end
# Range
(1..5).each { |n| puts n }
```
### Map (Collect)
```ruby
# Transform each element
numbers = [1, 2, 3, 4, 5]
squared = numbers.map { |n| n ** 2 }
puts squared # [1, 4, 9, 16, 25]
# With symbol to_proc
names = ["alice", "bob", "charlie"]
upcased = names.map(&:upcase)
puts upcased # ["ALICE", "BOB", "CHARLIE"]
```
### Select (Find All)
```ruby
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = numbers.select { |n| n.even? }
puts evens # [2, 4, 6, 8, 10]
odds = numbers.reject { |n| n.even? }
puts odds # [1, 3, 5, 7, 9]
```
### Reduce (Inject)
```ruby
numbers = [1, 2, 3, 4, 5]
sum = numbers.reduce(0) { |acc, n| acc + n }
puts sum # 15
product = numbers.reduce(1) { |acc, n| acc * n }
puts product # 120
```
### Find (Detect)
```ruby
numbers = [1, 2, 3, 4, 5]
first_even = numbers.find { |n| n.even? }
puts first_even # 2
all_evens = numbers.all? { |n| n.even? } # false
any_even = numbers.any? { |n| n.even? } # true
none_negative = numbers.none? { |n| n < 0 } # true
```
### Other Useful Iterators
```ruby
numbers = [1, 2, 3]
# each_with_index
numbers.each_with_index do |num, index|
puts "#{index}: #{num}"
end
# each_with_object
numbers.each_with_object([]) { |n, arr| arr << n * 2 } # [2, 4, 6]
# count
numbers.count # 3
numbers.count { |n| n > 1 } # 2
# include?
numbers.include?(2) # true
```
## Loop Control
### Break
```ruby
# Exit loop early
numbers = [1, 2, 3, 4, 5]
numbers.each do |n|
break if n == 3
puts n
end
# Output: 1, 2
```
### Next
```ruby
# Skip to next iteration
numbers = [1, 2, 3, 4, 5]
numbers.each do |n|
next if n.even?
puts n
end
# Output: 1, 3, 5
```
### Redo
```ruby
# Redo current iteration
counter = 0
5.times do
counter += 1
if counter < 3
puts counter
redo
end
end
```
### Retry
```ruby
# Retry entire block (often in rescue)
retry_count = 0
begin
# Simulate failure
raise "Error" if retry_count < 2
puts "Success"
rescue
retry_count += 1
retry
end
```
## Infinite Loops
```ruby
# Be careful!
loop do
puts "Press Ctrl+C to stop"
# break is required
end
```
## Summary
- `if`/`unless`: conditional execution
- `case`/`when`: multi-way comparison
- `while`/`until`: loops with condition
- `for`: iterate over ranges/collections
- Iterators: `each`, `map`, `select`, `reduce`, `find`
- Loop control: `break` (exit), `next` (skip), `redo` (retry iteration)
- Modifier form: `puts "hi" if valid`
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →