Сравнение двух лямбд / проков в Ruby - PullRequest
3 голосов
/ 17 июля 2010

Это сводит меня с ума, я публикую здесь после долгих осмотров.

Я хотел бы знать, если две переменные, указывающие на один и тот же Proc, указывают на один и тот же Proc.Я уверен, что это должно быть что-то, чего я не понимаю, например, почему все они возвращают false?

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)

Спасибо, Марк, вы сделали это намного яснее.В предыдущем он возвращал новые объекты каждый раз, так что равно?функция никогда не собиралась возвращать истину.Две лямбды были функционально одинаковыми, но не одним и тем же объектом.Поэтому, если вы создадите одну версию, а затем вернете ее обратно в метод, вы сможете проверить ее идентичность.Следующее имеет больше смысла и работает так, как я намеревался.

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 ]

6 голосов
/ 17 июля 2010

Хотя лямбда фактически эквивалентна, каждый вызов LambdaFunctions.LambdaFunction1 возвращает новый экземпляр лямбды.Было бы разумно, чтобы процы были эквивалентны только по тождеству, а не по значению, поскольку было бы практически невозможно определить программную эквивалентность.

Я имею в виду, если бы проки можно было определить как эквивалентные на основе того, чтоони сделали, тогда lambda { 3 } и lambda { 1 + 2 } будут эквивалентны.С лямбдами, более сложными, чем это, для определения эквивалентности в основном потребуется решение проблемы остановки .

Чтобы определить эквивалентную идентичность (согласно комментарию), обратитесь к Object #равно? :

В отличие от ==, метод equal? никогда не должен быть переопределен подклассами: он используется для определения идентичности объекта (то есть, a.equal?(b) тогда aэто тот же объект, что и b).

Если вам действительно нужно, чтобы a и b были одним и тем же объектом, вам нужно каждый раз возвращать одну и ту же лямбду;это означает, что вам нужно присвоить лямбду переменной экземпляра в классе 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 
0 голосов
/ 30 декабря 2015

Использование метода equals для равенства может оказаться не тем, что вы намереваетесь, он вернет true, только если два сравниваемых объекта ссылаются на один и тот же объект. Я думаю, что ==, возможно, вы бы предпочли в этом случае.

Я создал камень proc_extensions , чтобы получить источник прока или лямбды. Вы можете использовать это, чтобы сравнить источники двух процедур или лямбда, как это:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...