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