Ruby中的proc和lambda有什么区别?

Tom*_*man 168 ruby

什么时候你会使用一个而不是另一个?

jtb*_*des 251

一个区别在于它们处理参数的方式.使用proc {}和创建一个Proc.new {}等效的proc .但是,using lambda {}会给你一个proc来检查传递给它的参数的数量.来自ri Kernel#lambda:

相当于Proc.new,除了生成的Proc对象,检查调用时传递的参数数量.

一个例子:

p = Proc.new {|a, b| puts a**2+b**2 } # => #<Proc:0x3c7d28@(irb):1>
p.call 1, 2 # => 5
p.call 1 # => NoMethodError: undefined method `**' for nil:NilClass
p.call 1, 2, 3 # => 5
l = lambda {|a, b| puts a**2+b**2 } # => #<Proc:0x15016c@(irb):5 (lambda)>
l.call 1, 2 # => 5
l.call 1 # => ArgumentError: wrong number of arguments (1 for 2)
l.call 1, 2, 3 # => ArgumentError: wrong number of arguments (3 for 2)
Run Code Online (Sandbox Code Playgroud)

另外,正如Ken指出的那样,return在lambda内部使用返回该lambda的值,但是return在proc中使用从封闭块返回.

lambda { return :foo }.call # => :foo
return # => LocalJumpError: unexpected return
Proc.new { return :foo }.call # => LocalJumpError: unexpected return
Run Code Online (Sandbox Code Playgroud)

因此,对于大多数快速使用它们是相同的,但如果您想要自动严格的参数检查(有时也可以帮助调试),或者如果您需要使用该return语句来返回proc的值,请使用lambda.

  • 是否准确地说lambdas非常类似于方法(检查参数和返回将从它们返回),而procs非常类似于块(参数未被检查,返回将从包含方法或lambda返回)? (7认同)
  • 天知道现在我已经访问了多少网站和文章,似乎没有人谈论 Procs、方法和 lambda 的实用性。每个解释都只是提供了返回值等如何不同的令人毛骨悚然的细节,但没有解释为什么它很重要。现在我不得不得出结论,这是 Ruby 中的设计混乱。 (5认同)

sho*_*aib 72

procs和lambdas之间的真正区别与控制流关键字有关.我说的是return,raise,break,redo,retry等等-这些控制字.假设你在proc中有一个return语句.当你调用你的proc时,它不仅会将你抛弃,而且还会从封闭的方法返回,例如:

def my_method
  puts "before proc"
  my_proc = Proc.new do
    puts "inside proc"
    return
  end
  my_proc.call
  puts "after proc"
end

my_method

shoaib@shoaib-ubuntu-vm:~/tmp$ ruby a.rb
before proc
inside proc
Run Code Online (Sandbox Code Playgroud)

方法中的最后一个puts从未执行过,因为当我们调用proc时,return内部将我们从方法中抛弃.但是,如果我们将proc转换为lambda,则会得到以下结果:

def my_method
  puts "before proc"
  my_proc = lambda do
    puts "inside proc"
    return
  end
  my_proc.call
  puts "after proc"
end

my_method
shoaib@shoaib-ubuntu-vm:~/tmp$ ruby a.rb
before proc
inside proc
after proc
Run Code Online (Sandbox Code Playgroud)

lambda中的返回仅将我们从lambda本身转出,封闭方法继续执行.在procs和lambdas中处理控制流关键字的方式是它们之间的主要区别


Arv*_*ngh 10

# 过程示例

p = Proc.new { |x| puts x*2 }
[1,2,3].each(&p)              # The '&' tells ruby to turn the proc into a block 

proc = Proc.new { puts "Hello World" }
proc.call
Run Code Online (Sandbox Code Playgroud)

# Lambda 示例

lam = lambda { |x| puts x*2 }
[1,2,3].each(&lam)

lam = lambda { puts "Hello World" }
lam.call           
Run Code Online (Sandbox Code Playgroud)

Procs 和 Lambdas 之间的差异

在我讨论 procs 和 lambdas 之间的区别之前,重要的是要提到它们都是 Proc 对象。

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

proc.class # returns 'Proc'
lam.class  # returns 'Proc'
Run Code Online (Sandbox Code Playgroud)

但是,lambda 是 procs 的另一种“风味”。返回对象时会显示这种细微差别。

proc   # returns '#<Proc:0x007f96b1032d30@(irb):75>'
lam    # returns '<Proc:0x007f96b1b41938@(irb):76 (lambda)>'
Run Code Online (Sandbox Code Playgroud)

1. Lambdas 检查参数的数量,而 procs 不检查

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)
Run Code Online (Sandbox Code Playgroud)

相比之下,procs 并不关心它们是否传递了错误数量的参数。

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
Run Code Online (Sandbox Code Playgroud)

2. Lambdas 和 procs 以不同的方式对待 'return' 关键字

lambda 内部的“return”触发 lambda 代码外部的代码

def lambda_test
  lam = lambda { return }
  lam.call
  puts "Hello world"
end

lambda_test                 # calling lambda_test prints 'Hello World'
Run Code Online (Sandbox Code Playgroud)

proc 内的“return”触发正在执行 proc 的方法外的代码

def proc_test
  proc = Proc.new { return }
  proc.call
  puts "Hello world"
end

proc_test                 # calling proc_test prints nothing
Run Code Online (Sandbox Code Playgroud)

并回答您的其他查询,使用哪个以及何时使用?我会按照他提到的@jtbandes 关注

因此,对于大多数快速使用,它们是相同的,但是如果您想要自动严格参数检查(有时也可以帮助调试),或者如果您需要使用 return 语句返回 proc 的值,请使用 lambda。

最初发布在这里


Raj*_*hra 6

只有两个主要区别。

  • 首先,a lambda检查传递给它的参数数量,而a proc不检查。这意味着,lambda如果您传递错误数量的参数,则a 将引发错误,而a proc将忽略意外的参数,并将其分配nil给所有遗漏的参数。
  • 其次,当a lambda返回时,它将控制权传递回调用方法;当proc返回时,它将立即执行操作,而无需返回调用方法。

要查看其工作原理,请看下面的代码。我们的第一种方法称为a proc; 第二个叫a lambda

def batman_ironman_proc
  victor = Proc.new { return "Batman will win!" }
  victor.call
  "Iron Man will win!"
end

puts batman_ironman_proc # prints "Batman will win!"

def batman_ironman_lambda
  victor = lambda { return "Batman will win!" }
  victor.call
  "Iron Man will win!"
end

puts batman_ironman_lambda # prints "Iron Man will win!"
Run Code Online (Sandbox Code Playgroud)

看看proc“蝙蝠侠将获胜!” 的说法,这是因为它立即返回,而无需返回batman_ironman_proc方法。

lambda但是,我们的方法在被调用后返回该方法,因此该方法返回它评估的最后一个代码:“铁人将获胜!”