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