综合
Ruby のブロックと yield を一番簡単な例で
Kaziu Dev.to (EN Zone)
1 浏览
Ruby を書いていると必ず出てくる「ブロック」と「yield」。
難しく見えますが、要は 「処理を渡す」「渡された処理を実行する」 だけです。
ブロックとは
メソッドに渡す「処理のかたまり(コードの切れ端)」 のこと。
{ } か do...end で囲みます。
[1, 2, 3].each { |n| puts n }
# └──────────┘ これがブロック
.each に「各要素で puts n してね」という指示書を渡しています。
1
2
3
{ } と do...end は同じもの。長いときは do...end を使うだけです。
[1, 2, 3].each do |n|
puts n
end
yield とは
メソッドの中の「yield と書いた場所」で、渡されたブロックを実行する命令。
def あいさつ
puts "こんにちは"
yield # ← ここで渡されたブロックを実行
puts "さようなら"
end
あいさつ { puts "元気ですか?" }
こんにちは
元気ですか? ← yield の場所にブロックが差し込まれる
さようなら
yield は好きな場所に置け、何回でも呼べ、値も渡せます。
def 数える
yield 1
yield 2
end
数える { |n| puts "#{n}番目" }
# 1番目
# 2番目
2つの関係
ブロック = 渡す「やることメモ」(呼ぶ側が書く)
yield = そのメモを実行する命令(メソッド側が書く)
差し込む場所を決めるのがメソッド、差し込む中身を決めるのが呼ぶ側。
実践編:yield で処理を「挟み込む」
yield の本当に便利な使い方が、共通の前処理と後始末で、渡された処理を挟むパターンです。
def with_debug
old = Rails.logger.level
Rails.logger.level = :debug # 前処理:ログを debug に
yield # 呼び出し側の処理を実行
ensure # エラーが起きても起きなくても、最後に必ず実行される(=finally)
Rails.logger.level = old # 後始末:必ず元に戻す
end
使い方:
with_debug do
# この中だけログが debug になる
user.save!
end
# ここを抜けると自動で元のログレベルに戻る
なぜ便利か
共通部分(ログ切替と復元)を1か所にまとめられる。使う側は「何をしたいか」だけ書けばよい。
ensure で後始末が保証される。ブロックの中でエラーが起きても、ログレベルは必ず元に戻る。
もし yield を使わなければ、使う場所ごとに「切替 → 処理 → 復元」を毎回コピペする羽目になります。yield なら枠(前後処理)はメソッド側、中身は呼ぶ側、ときれいに分けられます。
もう一つの例:処理時間を測る
同じパターンで「実行時間の計測」も書けます。
def measure(label)
start = Time.now
yield
ensure
puts "#{label}: #{Time.now - start}秒"
end
measure("重い処理") do
heavy_task
end
# => 重い処理: 1.23秒
「共通の前後処理でブロックを挟む」 ——これは Ruby で頻出の設計パターンです。
File.open { |f| ... }(開いて必ず閉じる)なども、この仲間です。
阅读原文:https://dev.to/kaziusan/ruby-noburotukuto-yield-wo-fan-jian-dan-nali-de-3c3k
相关文章
评论0
还没有评论,来抢沙发吧