[plt-scheme] When does eqv? differ from eq? , from equal?
Woodhouse Gregory wrote:
>
> I almost always perform tests with eq? or equal?, seldom (if ever)
> with eqv? . The Reference is a bit mysterious, saying (in section 3.1)
>
> Two values are eqv?
> <file:///Applications/PLT%20Scheme%20Full%20v4.1.0.3/doc/reference/booleans.html#%28def._%28%28quote._%7E23%7E25kernel%29._eqv%7E3f%29%29>
> if and only if they are eq?
> <file:///Applications/PLT%20Scheme%20Full%20v4.1.0.3/doc/reference/booleans.html#%28def._%28%28quote._%7E23%7E25kernel%29._eq%7E3f%29%29>,
> unless otherwise specified for a particular datatype.
>
> That doesn't help much. Well, it /does/ help, but only by telling me
> that they are usually the same. Heuristically, I think of eq? as being
> similar to comparing pointers in C and equal? as a test that might
> involve library call that could run in time proportional to the size
> of the objects (e.g., strcmp). What is the intuition behind eqv?
>
I looked at the source for eqv and it seems to only be useful in a very
small set of cases, mostly for numbers.
I've added some comments below:
int scheme_eqv (Scheme_Object *obj1, Scheme_Object *obj2)
{
Scheme_Type t1, t2;
/* test if the objects are eq? */
if (SAME_OBJ(obj1, obj2))
return 1;
t1 = SCHEME_TYPE(obj1);
t2 = SCHEME_TYPE(obj2);
/* if they aren't the same type then #f */
if (NOT_SAME_TYPE(t1, t2)) {
#ifdef MZ_USE_SINGLE_FLOATS
/* If one is a float and the other is a double, coerce to double */
if ((t1 == scheme_float_type) && (t2 == scheme_double_type))
return double_eqv(SCHEME_FLT_VAL(obj1), SCHEME_DBL_VAL(obj2));
else if ((t2 == scheme_float_type) && (t1 == scheme_double_type))
return double_eqv(SCHEME_DBL_VAL(obj1), SCHEME_FLT_VAL(obj2));
#endif
return 0;
#ifdef MZ_USE_SINGLE_FLOATS
} else if (t1 == scheme_float_type) {
return double_eqv(SCHEME_FLT_VAL(obj1), SCHEME_FLT_VAL(obj2));
#endif
/* otherwise if the two types are double, complex, rational, or a char
then do some equality testing, otherwise #f */
} else if (t1 == scheme_double_type) {
return double_eqv(SCHEME_DBL_VAL(obj1), SCHEME_DBL_VAL(obj2));
} else if (t1 == scheme_bignum_type)
return scheme_bignum_eq(obj1, obj2);
else if (t1 == scheme_rational_type)
return scheme_rational_eq(obj1, obj2);
else if (t1 == scheme_complex_type) {
Scheme_Complex *c1 = (Scheme_Complex *)obj1;
Scheme_Complex *c2 = (Scheme_Complex *)obj2;
return scheme_eqv(c1->r, c2->r) && scheme_eqv(c1->i, c2->i);
} else if (t1 == scheme_char_type)
return SCHEME_CHAR_VAL(obj1) == SCHEME_CHAR_VAL(obj2);
else
return 0;
}