eq ?, eqv?,equal ?,和=在Scheme中有什么区别? [英] What is the difference between eq?, eqv?, equal?, and = in Scheme?

查看:675
本文介绍了eq ?, eqv?,equal ?,和=在Scheme中有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道这些操作之间有什么不同。我在堆栈溢出中看到了类似的问题,但它们是关于Lisp的,并且这三个操作符之间没有比较。所以,如果已经有人问我,请告诉我。



我在Scheme中编写不同类型的命令,并得到以下输出:

 (eq?5 5) - > #t 
(eq?2.5 2.5) - > #f
(等于2.5 2.5) - > #t
(= 2.5 2.5) - > #t

有人可以解释为什么会出现这种情况吗?

解决方案

我会逐步回答这个问题。让我们从 = 等价谓词开始。 = 谓词用于检查两个数字是否相等。如果你只提供了一个数字,那么它会引发一个错误:

 (= 2 3)=> #f 
(= 2.5 2.5)=> #t
(='()'())=>错误

eq?谓词用于检查它的两个参数是否存在于内存中的同一个对象。例如:

 (define x'(2 3))
(define y'(2 3))
(eq?xy)=> #f
(define y x)
(eq?x y)=> #t

请注意,只有一个空列表'()在内存中(实际上空列表不存在于内存中,但指向内存位置 0 的指针被视为空列表)。因此,比较空列表 eq?总是会返回 #t (因为它们表示内存中的相同对象):

 (define x'())
(define y'())
(eq?xy) => #t

现在取决于实现 eq?可能或不可以为原始值返回 #t ,例如数字,字符串等。例如:

 (eq?2 2)=>取决于实现
(eq?aa)=>取决于实施

这就是 eqv? eqv? eq?谓词完全相同,只是它总是返回 #t 为相同的原始值。例如:

 (eqv?2 2)=> #t 
(eqv?aa)=>取决于实施

因此 eqv?是一个超集 eq?,对于大多数情况下,您应该使用 eqv?而不是 eq? 。



最后我们来看等于?谓词。 等于?谓词与 eqv?谓词完全相同,除了它也可以用于测试是否两个列表,矢量等具有满足 eqv?谓词的对应元素。例如:

 (define x'(2 3))
(define y'(2 3))
(等于xy)=> #t
(eqv?x y)=> #f

一般来说:


  1. 当您希望测试两个数字是否相等时,使用 = 谓词。 使用 eqv?谓词,当您希望测试两个非数字值是否相等时。 code>谓词,当你想测试两个列表,矢量等是否相等时。 $ c>谓词,除非您确切地知道您在做什么。


I wonder what the difference is between those operations. I have seen similar questions in Stack Overflow but they are about Lisp, and there is not a comparison between three of those operators. So if this has been asked already, please let me know.

I am writing the different types of commands in Scheme, and I get the following outputs:

(eq? 5 5) -->#t
(eq? 2.5 2.5) -->#f
(equal? 2.5 2.5) --> #t
(= 2.5 2.5) --> #t

Can someone explain why this is the case?

解决方案

I'll answer this question incrementally. Let's start with the = equivalence predicate. The = predicate is used to check whether two numbers are equal. If you supply it anything else but a number then it will raise an error:

(= 2 3)     => #f
(= 2.5 2.5) => #t
(= '() '()) => error

The eq? predicate is used to check whether its two parameters respresent the same object in memory. For example:

(define x '(2 3))
(define y '(2 3))
(eq? x y)         => #f
(define y x)
(eq? x y)         => #t

Note however that there's only one empty list '() in memory (actually the empty list doesn't exist in memory, but a pointer to the memory location 0 is considered as the empty list). Hence when comparing empty lists eq? will always return #t (because they represent the same object in memory):

(define x '())
(define y '())
(eq? x y)      => #t

Now depending upon the implementation eq? may or may not return #t for primitive values such as numbers, strings, etc. For example:

(eq? 2 2)     => depends upon the implementation
(eq? "a" "a") => depends upon the implementation

This is where the eqv? predicate comes into picture. The eqv? is exactly the same as the eq? predicate, except that it will always return #t for same primitive values. For example:

(eqv? 2 2)     => #t
(eqv? "a" "a") => depends upon the implementation

Hence eqv? is a superset of eq? and for most cases you should use eqv? instead of eq?.

Finally we come to the equal? predicate. The equal? predicate is exactly the same as the eqv? predicate, except that it can also be used to test whether two lists, vectors, etc. have corresponding elements which satisfy the eqv? predicate. For example:

(define x '(2 3))
(define y '(2 3))
(equal? x y)      => #t
(eqv? x y)        => #f

In general:

  1. Use the = predicate when you wish to test whether two numbers are equivalent.
  2. Use the eqv? predicate when you wish to test whether two non-numeric values are equivalent.
  3. Use the equal? predicate when you wish to test whether two lists, vectors, etc. are equivalent.
  4. Don't use the eq? predicate unless you know exactly what you're doing.

这篇关于eq ?, eqv?,equal ?,和=在Scheme中有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆