比较 Ruby 中的两个 lambda/Proc
这让我发疯,我在四处寻找之后才在这里发帖。
我想知道指向同一个 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)
谢谢马克,你说得更清楚了。 以前它每次都返回新对象,所以相等吗?函数永远不会返回 true。这两个 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
This has been driving me nuts, I'm posting here after a lot of looking around.
I'd like to know if two variables pointing to the same Proc are the pointing to the same Proc.
I'm sure it must be something I'm not getting so for example why do all of these return 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)
Thank you Mark, you made it a lot clearer.
In previous it was returning new objects each time so the equal? function was never going to return true. The two lambdas were functionally the same but not the same object.
So if you create one version and then return it back in the method you can test it's identity.
The following makes more sense and works as I intended.
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
虽然 lambda 实际上是等价的,但每次调用
LambdaFunctions.LambdaFunction1
都会返回 lambda 的一个新实例。对于过程来说,仅通过身份(而不是通过值)进行等效是有意义的,因为实际上不可能确定程序等效性。我的意思是,如果 procs 可以根据它们所做的事情被确定为等效,那么 lambda { 3 } 和 lambda { 1 + 2 } 将是等效的。对于比这更复杂的 lambda,要确定等效性基本上需要解决停止问题 。
要确定等效标识(根据评论),请参阅 Object#equal? :
如果您确实需要
a
和b
是同一个对象,那么您需要每次都返回相同的 lambda;这意味着您需要将 lambda 分配给 LambdaFunctions 类中的实例变量,然后返回该变量。While the lambda is effectively equivalent, each call to
LambdaFunctions.LambdaFunction1
returns a new instance of the lambda. It would make sense for procs to be equivalent only by identity, not by value, since it would be virtually impossible to determine programmatic equivalence.What I mean is, if procs could be determined to be equivalent based on what they did, then
lambda { 3 }
andlambda { 1 + 2 }
would be equivalent. With lambdas any more complicated than that, to determine equivalence would basically require a solution to the halting problem.To determine equivalent identity (per the comment), refer to Object#equal?:
If you really need
a
andb
to be the same object, then you need to return the same lambda every time; this means you need to assign the lambda to an instance variable in theLambdaFunctions
class, for instance, and return that.使用
equals
方法进行相等可能不是您想要的,只有当比较的两个对象引用同一对象时,它才会返回true
。我认为在这种情况下==
可能是您更喜欢的。我创建了一个 proc_extensions gem 来获取 proc 或 lambda 的源代码。您可以使用它来比较两个 procs 或 lambda 的来源,如下所示:
Using the
equals
method for equality may not be what you intend it will only returntrue
if the two objects being compared refer to the same object. I think==
is perhaps what you might prefer in this case.I created a proc_extensions gem to get the source of a proc or lambda. You could use this to compare the sources of two procs or lambda like this: