2023-04-20 - Iterators and Blocks


main topics


new concept

blocks

Blocks are passed to methods. Think of blocks as anonymous functions that can take zero or more arguments.

['bruno', 'anne', 'augusto', 'yuri'].each do |name|
  puts "Hello, #{name}!"
end  
# Hello, bruno!
# Hello, anne!
# Hello, augusto!
# Hello, yuri!

# oneline syntax
doubles = numbers.map { |n| n * 2 }

A method that can receive a block must use the yield where the block is to be executed.

# example
def beautify_name(first_name, last_name)
  full_name = "#{first_name.capitalize} #{last_name.upcase}"
  yield(full_name)
end
Opinion

I think it's a shame that there is not any indication in a method's signature that it can receive a block. ☹️

Proc

During the love message challenge I learned that to pass a block to another method, we prefix it with &.


Iterators

Iterators are methods to iterate over a collection (such as an Array or a Hash)

# #each
########################################
musicians.each do |musician|
  puts "Hello, #{musician}!"
end

# #each_with_index
########################################
musicians.each_with_index do |musician, i|
  puts "#{index + 1} - #{musician}"
end

# #map - return something for each iteration
########################################
# example 1:
upcased_musicians = musicians.map do |musician|
  musician.upcase
end

# example 2:
first_names = musicians.map do |musician|
  musician.split.first
end

# #count - count elements matching a condition
########################################
r_musicians_count = musicians.count do |musician|
  musician.start_with?("R")
end

# #select
########################################
r_musicians = musicians.select do |musician|
  musician.start_with?("R")
end

Range

# from 0 to 10, including the boundaries
0..10

# excluding the upper boundary
0...10

# converting to an array
(0..10).to_a