Ruby 的程式碼區塊 是一等公民,可像變數一樣傳遞、儲存、呼叫。對應概念:Python 的 lambda/函式指標、C 的函式指標、Java 的匿名內部類/函式介面、JavaScript 的箭頭函式。
# 大括號形式(單行慣用)
{ puts "Hello, Block!" }
# do...end 形式(多行慣用)
do
puts "第一行"
puts "第二行"
end
def call_block
puts "方法開始"
yield if block_given? # 安全檢查
puts "方法結束"
end
call_block { puts "區塊被執行了" }
# 輸出:
# 方法開始
# 區塊被執行了
# 方法結束
def fibonacci(stop)
a, b = 0, 1
while a < stop
yield a
a, b = b, a + b
end
end
fibonacci(20) { |n| print "#{n} " } # 0 1 1 2 3 5 8 13
# Array#each
animals = ["貓", "狗", "鳥"]
animals.each { |animal| puts "#{animal} 叫聲" }
# Hash#each
scores = { "Alice" => 95, "Bob" => 87 }
scores.each { |name, score| puts "#{name}: #{score}" }
# Integer#times
3.times { puts "Ruby 很酷!" }
# Range#each
(1..5).each { |i| print "#{i} " }
# 方式 1:Proc.new
greeter = Proc.new { |name| puts "Hello, #{name}!" }
# 方式 2:lambda(較嚴格參數檢查、return 行為不同)
greeter_lambda = ->(name) { puts "Hello, #{name}!" }
# 方式 3:& 運算子將區塊轉為 Proc(方法參數接收)
def run(&block)
block.call("from method")
end
run { |msg| puts msg }
greeter.call("World") # Hello, World!
greeter_lambda.call("Ruby") # Hello, Ruby!
| 特性 | Proc | Lambda |
|---|---|---|
| 參數檢查 | 寬鬆(多參數忽略、少參數補 nil) | 嚴格(數量不符拋 ArgumentError) |
| return 行為 | 從定義 Proc 的**外層方法**返回 | 從 **Lambda 自身**返回 |
| 建立語法 | Proc.new { } | ->(x) { } 或 lambda { } |
# 策略模式:演算法外部化
def process(data, strategy)
strategy.call(data)
end
upcase = ->(s) { s.upcase }
reverse = ->(s) { s.reverse }
process("hello", upcase) # "HELLO"
process("hello", reverse) # "OLLEH"
# 延遲執行:交易腳本
class Transaction
def initialize
@steps = []
end
def add_step(&block)
@steps << block
end
def execute
@steps.each(&:call)
end
end
tx = Transaction.new
tx.add_step { puts "步驟 1: 扣款" }
tx.add_step { puts "步驟 2: 發貨" }
tx.execute
yield 執行傳入區塊。Proc/lambda 將區塊物件化,支援儲存、傳遞、多次呼叫。each, map, select, times...)讓集合操作極度簡潔。&block 參數與 block_given? 寫出靈活 API。