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是一種不一樣的「味道"。 返回對象時會顯示這種細微差異。code
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
Lambdas check the number of arguments, while procs do not
Lambdas and procs treat the ‘return’ keyword differently