今天的主題很老掉牙,你打關鍵字google會有一堆文章出現,至於為什麼還要寫呢,因為我開心你管我,因為在實作時超常碰到,必須要搞清楚才行,也趁此機會再摸得更熟。
在ruby中唯一不是物件的東西,它允許你將一段程式碼包裝在一個可被傳遞和執行的區塊中,花括號 {}
與 do..end
就是 Block。要接在方法(method)
後面,且無法單獨存活,會出錯,最後一行的執行結果就是回傳值。
[1, 2, 3].each { |x| puts x }
# or
[1, 2, 3].each do |x|
puts x
end
ruby貴為一個物件化很徹底的語言,怎麼會容許不是物件的存在呢?他有什麼長處呢?
通常使用yield
來執行Block,程式碼執行到puts my_method
時,會執行my_method
方法,先puts "Start of method"
,然後撞到yield
,將控制權交給Block去執行puts "哈囉!我是 Block"
,執行完畢再將控制權交還my_method方法
,然後puts "End of method"
。
def my_method
puts "Start of method"
yield
puts "End of method"
end
my_method do
puts "Inside the block"
end
puts my_method { puts "哈囉!我是 Block"}
#依序印出
Start of method
哈囉!我是 Block
End of method
用於檢查當前方法是否接收了一個 Block。這個方法通常在方法內部使用,以便根據是否有 Block 來執行不同的程式碼,當方法中有yield
,要判斷if block_given?
,不然在外面呼叫方法但後方沒有 Block 時會噴錯。
def my_method
yield if block_given?
end
my_method # 正常運作 但不會印出任何東西
my_method { puts "哈囉!我是 Block"} # 印出 哈囉!我是 Block
my_method do puts "哈囉!我是 Block" end # 印出 哈囉!我是 Block
do...end
是 Ruby 中的多行 Block 語法,通常用於多行程式碼塊。它使你可以在多行中定義 Block 內的程式碼。{}
花括號是 Ruby 中的單行 Block 語法,通常用於簡單的程式碼塊,可以簡潔地將 Block 定義在一行上。{}
優先權高於 do…end
list = [1,2,3,4,5]
p list.map { |x| x + 2 } # [3, 4, 5, 6, 7]
p list.map do |x| x + 2 end #<Enumerator: [1, 2, 3, 4, 5]:map> 只執行到 p(list.map) 就結束了
可被保存在變數中的程式碼塊,它可以被多次調用。Proc 通常用於封裝一個或多個程式碼塊,使其可以像一個變數一樣傳遞和使用,可以使Block物件化,並單獨存在。
使用 Proc.new
或 proc
方法來產生Proc物件。
# 方法1
proc1 = Proc.new { |x| x * 2 }
proc2 = Proc.new do
|x| x * 2
end
# 方法2
proc3 = proc { |x| x * 2 }
初階:
以下五種方法都可以調用Proc物件。
hello_world = Proc.new { puts 'hello!' }
hello_world.call
hello_world.()
hello_world [] # hello! => nil
hello_world ===
hello_world.yield
進階:
Proc傳遞參數,不會檢查參數數量。
my_proc = proc { |x, y| x + y }
my_proc.call(1, 2) # 正確,返回 3
my_proc.call(1) # 正確,返回 1
Proc作為參數傳遞
hello_world = Proc.new { |name| puts "hello #{name}"}
def perform_operation(x, operation)
result = operation.call(x)
puts result
end
perform_operation("Lilith", hello_world) # hello Lilith
與Proc相似,通常用於封裝一個或多個程式碼塊,使其可以像一個變數一樣傳遞和使用,可以使Block物件化,並單獨存在。
return
:**當 Lambda 內執行到 return
後,會將控制權交回給呼叫它的方法,繼續執行接下來的程式碼。# 方法1
lambda1 = lambda { |x| x * 2 }
# 方法2
lambda2 = ->(x){ x * 2 }
初階:
以下五種方法都可以調用Lambda物件。
hello_world = lambda { puts 'hello!' }
hello_world.call
hello_world.()
hello_world [] # hello! => nil
hello_world ===
hello_world.yield
進階:
Lambda傳遞參數,會對參數數量進行檢查,並回傳錯誤訊息。
my_lambda = lambda { |x, y| x + y }
my_lambda.call(1, 2) # 正確,返回 3
my_lambda.call(1) # 錯誤,引發 ArgumentError
Lambda作為參數傳遞
hello_world = lambda { |name| puts "hello #{name}"}
def perform_operation(x, operation)
result = operation.call(x)
puts result
end
perform_operation("Lilith", hello_world) # hello Lilith
參考資料: