💎

【Ruby 5日目】基本文法 - イテレータとブロック

に公開

はじめに

Rubyの最も強力な機能の一つであるイテレータとブロックについて解説します。

基本概念

ブロックは{}またはdo...endで囲まれたコードの塊です。メソッドに渡すことができ、yieldで実行されます。

イテレータはブロックを受け取って反復処理を行うメソッドです。each、map、select、rejectなどが代表的です。

使い方

# ブロックの基本
[1, 2, 3].each do |num|
  puts num
end

# 1行なら{}を使用
[1, 2, 3].each { |num| puts num }

# ブロック付きメソッドの定義
def repeat(n)
  n.times { yield }
end

repeat(3) { puts "Hello" }

# ブロック引数
def greet
  yield("Alice", 25)
end

greet do |name, age|
  puts "#{name}さん、#{age}歳"
end

よくあるユースケース

主要なイテレータメソッド

numbers = [1, 2, 3, 4, 5]

# map: 変換して新しい配列を返す
doubled = numbers.map { |n| n * 2 }
p doubled  #=> [2, 4, 6, 8, 10]

# select: 条件に合う要素を抽出
evens = numbers.select { |n| n.even? }
p evens  #=> [2, 4]

# reject: 条件に合わない要素を抽出
odds = numbers.reject { |n| n.even? }
p odds  #=> [1, 3, 5]

# reduce: 累積計算
sum = numbers.reduce(0) { |acc, n| acc + n }
p sum  #=> 15

# each_with_object: オブジェクトを渡しながら反復
hash = numbers.each_with_object({}) do |n, h|
  h[n] = n * 2
end
p hash  #=> {1=>2, 2=>4, 3=>6, 4=>8, 5=>10}

ブロックをProcとして扱う

# &をつけるとブロックをProcオブジェクトとして受け取れる
def execute(&block)
  puts "処理開始"
  block.call if block
  puts "処理終了"
end

execute { puts "メイン処理" }

# Procを変数に格納
double = Proc.new { |x| x * 2 }
p [1, 2, 3].map(&double)  #=> [2, 4, 6]

# Symbol#to_procの活用
names = ["alice", "bob", "charlie"]
p names.map(&:upcase)  #=> ["ALICE", "BOB", "CHARLIE"]
p names.map(&:capitalize)  #=> ["Alice", "Bob", "Charlie"]

注意点とベストプラクティス

  • 複数行ならdo...end、1行なら{}を使うのが慣習
  • yieldはブロックが渡されない場合エラーになるので、block_given?で確認
  • Symbol#to_proc(&:メソッド名)は簡潔で高速
  • ブロックは引数ではなく特別な存在(1つのメソッドに1つだけ)
  • Procとlambdaの違いを理解する(後日解説)

まとめ

イテレータとブロックについて学びました。実践的なコード例を通じて、Ruby 3.4の機能を活用できるようになりましょう。

参考資料

Discussion