Coder Talk:Ruby中_closures_的示例, 原文。編程
Plain old english:咱們想要運行的代碼分組方法。閉包
# Block Examples
[1,2,3].each { |x| puts x*2 } # blok is in between the curly braces
[1,2,3].each do |x|
puts x*2 # blok is everything between the do and end
end
# Proc Examples
p = Proc.new { |x| puts x*2 }
[1,2,3].each(&p) # The '&' tells Ruby to turn the proc into a blok
proc = Proc.new { puts "Hello World" }
proc.call # The body of the Proc object gets executed when called
# Lambda Examples
lam = lambda { |x| puts x*2 }
[1,2,3].each(&lam)
lam = lambda { puts "Hello World" }
lam.call
複製代碼
雖然看起來這些都很是類似,但我將在下面介紹一些細微差異。app
Procs are objects, blocks are notcurl
proc(注意小寫的p)是Proc類的一個實例。ide
p = Proc.new { puts "Hello World" }
複製代碼
這讓咱們能夠在其上調用方法並將其分配給變量。 Procs也能夠本身迴歸。函數
p.call # prints 'Hello World'
p.class # returns 'Proc'
a = p # a now equals p, a Proc instance
p # returns a proc object '#<Proc:0x007f96b1a60eb0@(irb):46>'
複製代碼
相比之下,blok只是方法調用的\ * syntax*的一部分。 它並不表明任何獨立的東西,只能出如今參數列表中。學習
{ puts "Hello World"} # syntax error
a = { puts "Hello World"} # syntax error
[1,2,3].each {|x| puts x*2} # only works as part of the syntax of a method call
複製代碼
相反,您能夠將多個過程傳遞給方法。ui
def multiple_procs(proc1, proc2)
proc1.call
proc2.call
end
a = Proc.new { puts "First proc" }
b = Proc.new { puts "Second proc" }
multiple_procs(a,b)
複製代碼
在得出進入procs和lambdas之間的差別以前,重要的是要提到它們都是Proc對象。url
proc = Proc.new { puts "Hello world" }
lam = lambda { puts "Hello World" }
proc.class # returns 'Proc'
lam.class # returns 'Proc'
複製代碼
然而,lambdas是一種不一樣的「味道"。 返回對象時會顯示這種細微差異。spa
proc # returns '#<Proc:0x007f96b1032d30@(irb):75>'
lam # returns '<Proc:0x007f96b1b41938@(irb):76 (lambda)>'
複製代碼
(lambda)符號提醒一下,雖然procs和lambdas很是類似,即便是Proc類的兩個實例,它們也略有不一樣。 如下是主要差別。
Lambdas check the number of arguments, while procs do not
lam = lambda { |x| puts x } # creates a lambda that takes 1 argument
lam.call(2) # prints out 2
lam.call # ArgumentError: wrong number of arguments (0 for 1)
lam.call(1,2,3) # ArgumentError: wrong number of arguments (3 for 1)
複製代碼
相反,過程並不關心它們是否傳遞了錯誤數量的參數。
proc = Proc.new { |x| puts x } # creates a proc that takes 1 argument
proc.call(2) # prints out 2
proc.call # returns nil
proc.call(1,2,3) # prints out 1 and forgets about the extra arguments
複製代碼
如上所示,若是傳遞了錯誤數量的參數,則procs不會出錯並引起錯誤。 若是proc須要參數但沒有傳遞參數,則proc返回nil。 若是傳遞的參數太多而忽略了額外的參數。
lambda中的'return'會在lambda代碼以外觸發代碼
def lambda_test
lam = lambda { return }
lam.call
puts "Hello world"
end
lambda_test yyy188zzzcalling lambda_test prints 'Hello World'
複製代碼
proc中的'return'觸發執行proc的方法以外的代碼
def proc_test
proc = Proc.new { return }
proc.call
puts "Hello world"
end
proc_test yyy188zzzcalling proc_test prints nothing
複製代碼
Coder Talk:'函數或對函數的引用以及引用環境。 與普通函數不一樣,閉包容許函數訪問non-local變量,即便在其直接詞法範圍以外調用它。' - Wikipedia
Plain old english:相似於一個手提箱,它是一組代碼,當打開(即調用)時,包含打包它時所包含的內容(即建立它)。
# Example of Proc objects preserving local context
def counter
n = 0
return Proc.new { n+= 1 }
end
a = counter
a.call # returns 1
a.call # returns 2
b = counter
b.call # returns 1
a.call # returns 3
複製代碼
Lambda的名字源於20世紀30年代引入的一種微積分,以幫助研究數學的基礎。 Lambda演算經過簡化其語義,有助於使可計算函數更容易學習。 這些簡化中最相關的是「匿名"處理函數,這意味着沒有給函數賦予明確的名稱。
sqsum(x,y) = x*x + y*y #<-- normal function
(x,y) -> x*x + y*y #<-- anonymous function
複製代碼
通常來講,在編程中,術語lambda指的是匿名函數。 這些匿名函數在某些語言(即Javascript)中是很是常見和明確的,而在其餘語言中是隱含的(即Ruby)。
Proc是程序的簡稱,程序是一組打包做爲執行特定任務的單元的指令。 在不一樣的語言中,這些能夠稱爲函數,例程,方法或通用術語可調用單元。 它們一般被屢次調用,並在程序中屢次調用。
Procs are objects, blocks are not 2. At most one block can appear in an argument list Lambdas check the number of arguments, while procs do not Lambdas and procs treat the ‘return’ keyword differently