Ruby 中使用 Lambda 和 Proc 保存塊
在Block的章節中,我們學習了在Ruby中學習了創建塊了兩種方式:{}
以及do...end
和如何在方法使用yield
以及使用call
來調用一個塊。今天我們學習將塊保存到變量的兩種形式:Labmbda 和Proc。
1. Proc
1.1 定義
Proc 有兩種表達方式:
say_something = Proc.new { puts "This is a proc" }
另外一種是:
say_something = proc { puts "This is a proc" }
1.2 調用
我們使用call
來執行 Proc 的代碼。
實例:
say_something = -> { puts "This is a proc" }
say_something.call
# ---- 輸出結果 ----
This is a proc
注意事項:Proc有很多種調用方式,但是我們只使用call
,不使用其它的。
實例:
my_proc = -> { puts "Proc called" }
my_proc.call
my_proc.()
my_proc[]
my_proc.===
# ---- 輸出結果 ----
Proc called
Proc called
Proc called
Proc called
1.3 接收參數
第一種寫法接收參數的形式為:
times_two = Proc.new {|x| x * 2 }
times_two.call(10)
# ---- 輸出結果 ----
20
第二種形式為:
times_two = proc {|x| x * 2 }
times_two.call(10)
# ---- 輸出結果 ----
20
2. Lambda
2.1 定義
Lambda 有兩種表達方式:
say_something = -> { puts "This is a lambda" }
另外一種是:
say_something = lambda { puts "This is a lambda" }
Tips:
->
這種寫法Ruby 1.9 以上版本才支持。
2.2 調用
定義 Lambda 不會在其中運行代碼,就像定義方法不會運行該方法一樣,您需要為此使用call
方法。
實例:
say_something = -> { puts "This is a lambda" }
say_something.call
# ---- 輸出結果 ----
This is a lambda
注意事項:Lambda同樣有很多種調用方式,但是我們依然只使用call
。
實例:
my_lambda = -> { puts "Lambda called" }
my_lambda.call
my_lambda.()
my_lambda[]
my_lambda.===
# ---- 輸出結果 ----
Lambda called
Lambda called
Lambda called
Lambda called
2.3 接收參數
Lambda 也可以接受參數。
實例:
times_two = ->(x) { x * 2 }
times_two.call(10)
# ---- 輸出結果 ----
20
注意,兩種 Lambda 的參數表現形式是不同的。
times_two = lambda {|x| x * 2 }
times_two.call(10)
# ---- 輸出結果 ----
20
如果將錯誤數量的參數傳遞給 Lambda,則將引發異常,就像常規方法一樣。
實例:
times_two = ->(x) { x * 2 }
times_two.call()
# ---- 輸出結果 ----
ArgumentError (wrong number of arguments (given 0, expected 1))
3. 比較 Proc 和 Lambda
3.1 創建形式不同,調用方法相同。
Lambda 和 Proc 本質上都Proc
類的對象,Proc 類有一個實例方法名為lambda?
puts proc { }.class
puts Proc.new {}.class
puts lambda {}.class
puts -> {}.class
# ---- 輸出結果 ----
Proc
Proc
Proc
Proc
3.2 對于接收參數后是否傳值反應不同
Proc 不在意是否真正傳入參數,Lambda 要求調用時傳入的參數必須和接收的參數保持一致,否則會拋出異常。
3.3 對于return語句的處理
Lambda 中使用return
語句和常規方法一樣。
實例:
my_lambda = lambda { return 1 }
puts "Lambda result: #{my_lambda.call}"
# ---- 輸出結果 ----
Lambda result: 1
Proc 則在當前上下文中使用return
。相當于在調用位置執行return
。
實例:
my_proc = proc { return 1 }
puts "Proc result: #{my_proc.call}"
# ---- 沒有輸出結果 ----
相當于:
puts "Proc result: #{return 1}"
# ---- 沒有輸出結果 ----
Tips:在低于Ruby 2.5 版本中,我們這種寫法會拋出異常
unexpected return (LocalJumpError)。
所以我們在 Proc 中使用return
的時候,一般結合方法來使用。
def proc_method
my_proc = proc { return 1 }
my_proc.call
end
puts "Proc result: #{proc_method}"
# ---- 輸出結果 ----
Proc result: 1
4. 小結
本章節我們學習了將塊保存到變量的兩種形式 Lambda 和 Proc,可以使用proc
和Proc.new
創建Proc,可以使用lambda
和->
創建 Lambda,調用它們要使用call
,了解了 Proc 和 Lambda 本質都是一樣的,都是Proc
類的實例。以及如何接收參數,對return
語句的處理。