This tutorial will guide you through the fundamentals of Ruby blocks, including their syntax, use cases, and real-world applications. You’ll learn how to leverage blocks for code reusability, iteration, and functional programming concepts.
Step 1: Introduction to Blocks
ruby
array = [1, 2, 3, 4, 5]
array.each { |num| puts num }Practice Exercise
Write a method called `triple` that takes a block as an argument. The method should iterate over the elements of an array and execute the block with each element multiplied by 3.
Show Solution
def triple(arr)
arr.map { |num| yield(num * 3) }
end
result = triple([1, 2, 3]) { |num| num }
puts result.inspect # Output: [3, 6, 9]
# Explanations:
# 1. The `triple` method takes an array `arr` as an argument.
# 2. Inside the method, we use the `map` method to iterate over the array.
# 3. For each element `num`, we call the `yield` keyword with `num * 3`.
# 4. The block `{ |num| num }` is passed to the `triple` method when it's called.
# 5. The block simply returns the value passed to it (num * 3).
# 6. The `map` method returns a new array with the transformed values.Step 2: Block Syntax
# Single-line block
[1, 2, 3].each { |num| puts num }
# Multi-line block
numbers = [1, 2, 3, 4, 5]
numbers.each do |num|
square = num ** 2
puts "The square of #{num} is #{square}"
endPractice Exercise
Write a method called `greet` that takes a block. The method should call the block and pass it the string `"Hello"`. Inside the block, concatenate the string with a name (e.g., `"Hello, Alice"`), and print the result.
Show Solution
def greet(&block)
name = "Alice"
block.call("Hello, #{name}")
end
greet { |greeting| puts greeting }
# Output: Hello, Alice
# Explanations:
# 1. The `greet` method takes a block using the `&block` parameter.
# 2. Inside the method, we define a `name` variable.
# 3. We call the block using `block.call` and pass it a string with the greeting and name.
# 4. Inside the block `{ |greeting| puts greeting }`, we print the greeting string.
# 5. The `call` method is used to execute the block and pass it the argument.Step 3: Blocks and Methods
def greet
yield "Hello"
yield "Goodbye"
end
greet { |greeting| puts greeting }
# Output:
# Hello
# GoodbyePractice Exercise
Write a method called apply_operation that takes a block and two numbers as arguments. The method should execute the block with the two numbers and return the result.
Show Solution
def apply_operation(num1, num2, &block)
block.call(num1, num2)
end
result = apply_operation(3, 4) { |a, b| a + b }
puts result # Output: 7
result = apply_operation(5, 2) { |a, b| a * b }
puts result # Output: 10
# Explanations:
# 1. The `apply_operation` method takes two arguments, `num1` and `num2`, and a block using `&block`.
# 2. Inside the method, we call the block using `block.call` and pass it `num1` and `num2` as arguments.
# 3. When calling the method, we pass a block that performs an operation (e.g., addition or multiplication).
# 4. The result of the block execution is returned by the method and can be stored in a variable.Step 4: Blocks and Iteration
array = [1, 2, 3, 4, 5]
# Iterate over the array
array.each { |num| puts num }
# Transform the array
doubled = array.map { |num| num * 2 }
puts doubled.inspect # Output: [2, 4, 6, 8, 10]
# Filter the array
even_numbers = array.select { |num| num.even? }
puts even_numbers.inspect # Output: [2, 4]Practice Exercise
Given an array of strings, write a method that takes a block and returns a new array containing only the strings that satisfy the condition defined in the block.
Show Solution
def filter_strings(strings, &block)
strings.select(&block)
end
words = ["apple", "banana", "cherry", "date", "elderberry"]
result = filter_strings(words) { |word| word.length > 5 }
puts result.inspect # Output: ["banana", "cherry", "elderberry"]
# Explanations:
# 1. The `filter_strings` method takes an array of strings `strings` and a block `&block`.
# 2. Inside the method, we use the `select` method and pass it the block using `&block`.
# 3. The `select` method returns a new array containing only the elements that satisfy the condition in the block.
# 4. When calling `filter_strings`, we pass a block that checks if the string length is greater than 5.
# 5. The method returns a new array with the strings that satisfy the condition in the block.Step 5: Blocks and Functional Programming
def calculate(num1, num2, operation)
operation.call(num1, num2)
end
addition = lambda { |a, b| a + b }
subtraction = lambda { |a, b| a - b }
result = calculate(5, 3, addition)
puts result # Output: 8
result = calculate(5, 3, subtraction)
puts result # Output: 2Practice Exercise
Write a method called `apply_operations` that takes an array of numbers and two lambda functions as arguments. The first lambda function should perform an operation on each number in the array, and the second lambda function should perform another operation on the results of the first lambda function. The method should return the final result.
Show Solution
def apply_operations(numbers, operation1, operation2)
result = numbers.map(&operation1)
result.map(&operation2)
end
double = lambda { |num| num * 2 }
square = lambda { |num| num ** 2 }
numbers = [1, 2, 3, 4, 5]
result = apply_operations(numbers, double, square)
puts result.inspect # Output: [4, 16, 36, 64, 100]
# Explanations:
# 1. The `apply_operations` method takes an array of numbers `numbers`, and two lambda functions `operation1` and `operation2`.
# 2. Inside the method, we use `map` to apply `operation1` to each number in the array, creating a new array `result`.
# 3. We then use `map` again on the `result` array, applying `operation2` to each element.
# 4. The final result is an array with the numbers transformed by both operations.
# 5. In the example, we define `double` and `square` lambda functions and pass them to `apply_operations`.
# 6. The method first doubles each number, then squares the doubled numbers, returning the final result.Sign in to take Cornell notes on this lesson — they save automatically and stay with your account.