比较Ruby中的两个lambda / Procs

时间:2010-07-16 22:35:33

标签: 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)
谢谢马克,你说得更清楚了。 在之前它每次都返回新对象,所以相等?功能永远不会回归真实。两个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

2 个答案:

答案 0 :(得分:6)

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

我的意思是,如果可以根据他们所做的事情确定触发器是等效的,那么lambda { 3 }lambda { 1 + 2 }将是等效的。使用lambdas比这更复杂,确定等价基本上需要halting problem的解决方案。

要确定等效身份(根据评论),请参阅Object#equal?

  

==不同,equal?方法永远不应被子类覆盖:它用于确定对象标识(即a.equal?(b) iff a是同一个对象作为b)。

如果你确实需要ab成为同一个对象,那么每次都需要返回相同的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 

答案 1 :(得分:0)

使用equals方法进行相等可能不是您想要的,如果被比较的两个对象引用同一个对象,它只会返回true。我认为在这种情况下你可能更喜欢==

我创建了一个proc_extensions gem来获取proc或lambda的来源。您可以使用它来比较两个proc或lambda的来源,如下所示:

require 'proc_extensions'

Proc.instance_eval { include ProcExtensions::Source }

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.source
func2 = LambdaFunctions.LambdaFunction1.source
func3 = LambdaFunctions.LambdaFunction2.source

func1 == func2 # => true
func1 == func3 # => true
func1 == LambdaFunctions.LambdaFunction1.source # => true
func3 == LambdaFunctions.LambdaFunction1.source # => true
func3 == LambdaFunctions.LambdaFunction2.source # => true