比较Ruby中的两个lambda/Procs

Cra*_*ton 3 ruby lambda

这让我疯了,经过大量的环顾后,我在这里发帖.

我想知道指向同一个Proc的两个变量是否指向同一个Proc.我敢肯定它一定是我没有得到的东西,例如为什么所有这些都返回错误?

class LambdaFunctions
  def self.LambdaFunction1
    lambda { |t| t ** 2}
  end
end

a = LambdaFunctions.LambdaFunction1
b = LambdaFunctions.LambdaFunction1

puts LambdaFunctions.LambdaFunction1
puts a
puts b

puts a == b
puts a === b
puts a.eql?(b)
puts a.equal?(b)
puts a == LambdaFunctions.LambdaFunction1
puts a === LambdaFunctions.LambdaFunction1
puts a.eql?(LambdaFunctions.LambdaFunction1)
puts a.equal?(LambdaFunctions.LambdaFunction1)
Run Code Online (Sandbox Code Playgroud)

谢谢Mark,你说得更清楚了.在之前它每次都返回新对象,所以相等?功能永远不会回归真实.两个lambda在功能上是相同但不是同一个对象.因此,如果您创建一个版本,然后在方法中将其返回,则可以测试它的身份.以下内容更有意义,并且按照我的意图运行.

class LambdaFunctions

  @lambda1 = lambda { |t| t ** 2}
  @lambda2 = lambda { |t| t ** 2}

  def self.LambdaFunction1
    @lambda1
  end

  def self.LambdaFunction2
    @lambda2
  end
end

func1 = LambdaFunctions.LambdaFunction1
func2 = LambdaFunctions.LambdaFunction1
func3 = LambdaFunctions.LambdaFunction2

puts func1.equal?(func2) # true
puts func1.equal?(func3) # false
puts func1.equal?(LambdaFunctions.LambdaFunction1) # true
puts func3.equal?(LambdaFunctions.LambdaFunction1) # false
puts func3.equal?(LambdaFunctions.LambdaFunction2) # true
Run Code Online (Sandbox Code Playgroud)

Mar*_*off 6

虽然拉姆达是有效等价,每次调用LambdaFunctions.LambdaFunction1返回拉姆达的新实例.只有通过身份,而不是价值,触发是有意义的,因为实际上不可能确定程序的等同性.

我的意思是,如果特效可以决定基于他们做了什么,然后是等价的lambda { 3 },并lambda { 1 + 2 }是等同的.使用lambdas比这更复杂,确定等效性基本上需要解决停止问题.

要确定等效身份(根据注释),请参阅Object#equal?:

与此不同==,该equal?方法永远不应被子类覆盖:它用于确定对象标识(即a.equal?(b)iff a与其相同的对象b).

如果你真的需要a并且b是同一个对象,那么你每次都需要返回相同的lambda; 这意味着您需要将lambda分配给LambdaFunctions类中的实例变量,并返回变量.

ruby-1.9.1-p378 > class LambdaFunctions
ruby-1.9.1-p378 ?>   @func1 = lambda { |t| t ** 2 }
ruby-1.9.1-p378 ?>   def self.LambdaFunction1
ruby-1.9.1-p378 ?>      @func1
ruby-1.9.1-p378 ?>    end
ruby-1.9.1-p378 ?>  end
 => nil 
ruby-1.9.1-p378 > a = LambdaFunctions.LambdaFunction1
 => #<Proc:0x0000010099e370@(irb):10 (lambda)> 
ruby-1.9.1-p378 > b = LambdaFunctions.LambdaFunction1 # same address as a
 => #<Proc:0x0000010099e370@(irb):10 (lambda)> 
ruby-1.9.1-p378 > a == b
 => true 
Run Code Online (Sandbox Code Playgroud)