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