1. 程式人生 > 程式設計 >在 Ruby 中,blok,proc 和 lambda 有什麼區別?

在 Ruby 中,blok,proc 和 lambda 有什麼區別?

bloks,procs和lambdas是什麼?

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,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,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,3].each(&lam) lam = lambda { puts "Hello World"
} lam.call 複製程式碼

雖然看起來這些都非常相似,但我將在下面介紹一些細微差別。

Blocks和Procs之間的差異

Procs are objects,blocks are not

proc(注意小寫的p)是Proc類的一個例項。

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,3].each {|x| puts x*2} # only works as part of the syntax of a method call

複製程式碼
  1. At most one block can appear in an argument list

相反,您可以將多個過程傳遞給方法。

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之間的差異

在得出進入procs和lambdas之間的差異之前,重要的是要提到它們都是Proc物件。

proc = Proc.new { puts "Hello world" }
lam = lambda { puts "Hello World" }

proc.class # returns 'Proc'
lam.class # returns 'Proc'

複製程式碼

然而,lambdas是一種不同的“味道"。 返回物件時會顯示這種細微差別。

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,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,3) # prints out 1 and forgets about the extra arguments

複製程式碼

如上所示,如果傳遞了錯誤數量的引數,則procs不會出錯並引發錯誤。 如果proc需要引數但沒有傳遞引數,則proc返回nil。 如果傳遞的引數太多而忽略了額外的引數。

  1. Lambdas and procs treat the ‘return’ keyword differently

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

複製程式碼

Background第1部分:Lambda微積分和匿名函式

Lambda的名字源於20世紀30年代引入的一種微積分,以幫助研究數學的基礎。 Lambda演算通過簡化其語義,有助於使可計算函式更容易學習。 這些簡化中最相關的是“匿名"處理函式,這意味著沒有給函式賦予明確的名稱。

sqsum(x,y) = x*x + y*y #<-- normal function
(x,y) -> x*x + y*y #<-- anonymous function

複製程式碼

一般來說,在程式設計中,術語lambda指的是匿名函式。 這些匿名函式在某些語言(即Javascript)中是非常常見和明確的,而在其他語言中是隱含的(即Ruby)。

Background第2部分:名稱過程來自何處

Proc是程式的簡稱,程式是一組打包作為執行特定任務的單元的指令。 在不同的語言中,這些可以稱為函式,例程,方法或通用術語可呼叫單元。 它們通常被多次呼叫,並在程式中多次呼叫。

Summary差異

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