Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between eq?, eqv?, equal?, and = in Scheme?

I wonder what the difference is between those operations in Scheme. I have seen similar questions in Stack Overflow but they are about Lisp, and there is not a comparison between three of those operators.

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 

Why is this the case?

like image 475
yrazlik Avatar asked Apr 30 '13 11:04

yrazlik


People also ask

What does EQ mean in Scheme?

equal? for numbers reduces to = , 2.5 and 2.5 are numerically equal. eq? compares 'pointers'. The number 5, in your Scheme implementation, is implemented as an 'immediate' (likely), thus 5 and 5 are identical.

How do you write not equal to in Scheme?

Since Scheme doesn't have a numeric "not equals" operator (like the != operator in C/Java/Python), we have to combine not and = in order to evaluate "not equals".


1 Answers

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.
like image 126
Aadit M Shah Avatar answered Oct 23 '22 08:10

Aadit M Shah