In Ruby, blocks, procs, and lambdas are powerful tools for handling chunks of code. They allow you to pass code to methods, store code in variables, and create reusable code snippets. Understanding these concepts is crucial for writing clean, efficient, and flexible Ruby code.
- Blocks
What is a Block?
A block is a chunk of code enclosed between do...end
or curly braces {...}
. Blocks are not objects, but they can be passed to methods and executed within those methods.
Syntax
# Using do...end [1, 2, 3].each do |number| puts number end # Using curly braces [1, 2, 3].each { |number| puts number }
Explanation
each
is a method that iterates over each element of the array.- The block
{ |number| puts number }
is passed to theeach
method. |number|
is a block parameter that takes the value of each element in the array.puts number
prints each element.
Practical Example
yield
is used to call the block passed to the method.- The block
{ |greeting| puts "#{greeting}, World!" }
is executed twice with different values.
- Procs
What is a Proc?
A Proc
(short for procedure) is an object that encapsulates a block of code, which can be stored in a variable, passed to methods, and called.
Syntax
Explanation
Proc.new
creates a newProc
object.my_proc.call("Alice")
executes the block with the argument "Alice".
Practical Example
def execute_proc(my_proc) my_proc.call("Bob") end my_proc = Proc.new { |name| puts "Hello, #{name}!" } execute_proc(my_proc)
execute_proc
method takes aProc
as an argument and calls it with "Bob".
- Lambdas
What is a Lambda?
A lambda is a special type of Proc
with stricter argument checking and different behavior for return
.
Syntax
Explanation
lambda
creates a new lambda object.my_lambda.call("Charlie")
executes the lambda with the argument "Charlie".
Practical Example
def execute_lambda(my_lambda) my_lambda.call("Dave") end my_lambda = lambda { |name| puts "Hello, #{name}!" } execute_lambda(my_lambda)
execute_lambda
method takes a lambda as an argument and calls it with "Dave".
Differences Between Procs and Lambdas
Feature | Proc | Lambda |
---|---|---|
Argument Checking | Does not enforce argument count | Enforces argument count |
Return Behavior | Returns from the enclosing method | Returns from the lambda itself |
Example of Differences
# Argument checking my_proc = Proc.new { |a, b| puts "Proc: #{a}, #{b}" } my_proc.call(1) # No error, prints "Proc: 1, " my_lambda = lambda { |a, b| puts "Lambda: #{a}, #{b}" } # my_lambda.call(1) # Error: wrong number of arguments (given 1, expected 2) # Return behavior def proc_return my_proc = Proc.new { return "Proc return" } my_proc.call "Method return" end def lambda_return my_lambda = lambda { return "Lambda return" } my_lambda.call "Method return" end puts proc_return # Prints "Proc return" puts lambda_return # Prints "Method return"
Exercises
Exercise 1: Using Blocks
Write a method repeat
that takes a number and a block, and calls the block that many times.
Solution
Exercise 2: Creating and Using Procs
Create a Proc
that takes a number and prints its square. Pass this Proc
to a method that calls it with different numbers.
square_proc = Proc.new { |number| puts number ** 2 } def call_proc(my_proc, number) # Your code here end call_proc(square_proc, 4) call_proc(square_proc, 5)
Solution
square_proc = Proc.new { |number| puts number ** 2 } def call_proc(my_proc, number) my_proc.call(number) end call_proc(square_proc, 4) call_proc(square_proc, 5)
Exercise 3: Creating and Using Lambdas
Create a lambda that takes a string and prints it in uppercase. Pass this lambda to a method that calls it with different strings.
uppercase_lambda = lambda { |str| puts str.upcase } def call_lambda(my_lambda, str) # Your code here end call_lambda(uppercase_lambda, "hello") call_lambda(uppercase_lambda, "world")
Solution
uppercase_lambda = lambda { |str| puts str.upcase } def call_lambda(my_lambda, str) my_lambda.call(str) end call_lambda(uppercase_lambda, "hello") call_lambda(uppercase_lambda, "world")
Conclusion
In this section, you learned about blocks, procs, and lambdas in Ruby. Blocks are chunks of code that can be passed to methods, procs are objects that encapsulate blocks, and lambdas are a special type of proc with stricter argument checking and different return behavior. Understanding these concepts will help you write more flexible and reusable code. In the next section, we will dive into metaprogramming, a powerful feature of Ruby that allows you to write code that writes code.
Ruby Programming Course
Module 1: Introduction to Ruby
Module 2: Basic Ruby Concepts
Module 3: Working with Collections
Module 4: Object-Oriented Programming in Ruby
- Classes and Objects
- Instance Variables and Methods
- Class Variables and Methods
- Inheritance
- Modules and Mixins
Module 5: Advanced Ruby Concepts
Module 6: Ruby on Rails Introduction
- What is Ruby on Rails?
- Setting Up Rails Environment
- Creating a Simple Rails Application
- MVC Architecture
- Routing
Module 7: Testing in Ruby
- Introduction to Testing
- Unit Testing with Minitest
- Behavior-Driven Development with RSpec
- Mocking and Stubbing