Re: What is eq? used for



bobueland@xxxxxxxxx writes:

> RUNNING (In DRScheme)
>
> (eq? 5 3) ==> #f
> (eq? 5 5) ==> #t
> (eq? 3/2 3/2) ==> #f
> (eq? 3/2 6/4) ==> #f
> (eq? 3.14 (+ 3.0 .14)) ==> #f
>
> (eq? null '()) ==> #t
> (eq? null ()) ==> #t
> (eq? #t 't) ==> #f
> (eq? "foo" 'foo) ==> #f
>
> (eq? 3 3.0) ==> #f
> (eq? 1+i 1+i) ==> #f
>
> (let ((x (* 8 2))) (eq? x x)) ==> #t
> (eq? #\a #\a) ==> #t
>
> (eq? #t #t) ==> #t
> (eq? #f #f) ==> #t
> (eq? #t #f) ==> #f
>
> (eq? (cdr '(a)) '()) ==> #t
> (eq? 'a 'a) ==> #t
> (eq? 'a (string->symbol "a")) ==> #t
>
> (eq? "abc" "abc") ==> #f
> (eq? car car) ==> #t
> (eq? (lambda (x) x) (lambda (y) y)) ==> #f
>
> It seems hard to guess when eq? will give true and when false. What is
> the use of eq? and is there some simple rule or way of thinking to
> conclude what answer eq? will give.
> I've read somewhere that "it is possible to implement eq? much more
> efficiently than eqv?, for example, as a simple pointer comparison".
> Does this have to do with the concepts of "deep copy" and "shallow
> copy"?

It's indeed related to the kind of copy.
http://www.nhplace.com/kent/PS/EQUAL.html

eq? compares the pointers that hide between some variables and values in lisp.

5 and 3 are fixnum, they can be held in one word along with their type
(fixnum), so we don't need to make pointers to them: we can store and
compare them directly.

For example:
31 3 0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| fixnum value |type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


3/2 and 3/2 are rationals, they are stored as a record of two pointers
and a type. For example:

31 0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| numerator |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| denominator |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

(The numerator or denominator themselves can be either fixnums like in
the case of 3/2, or bignums, in which case the numerator and/or
denominator will contain a pointer to the bignum).

Since two or more words cannot be held in a variable or register, we
put the rational record on the heap and keep a pointer to it in the
variable/register. eq? will then return #t only if the two variables
point to the same rational, not whe they point to two different
rationals that happen to be equal.

(eq? var var) is always #t.

Note that: (let ((r 3/2))
(let ((e (list 'eq? r r)))
(display e)
(eval e (SCHEME-REPORT-ENVIRONMENT 5))))
prints: (EQ? 3/2 3/2)
and returns: #t

but: (let ((e (list 'eq? 3/2 (/ 6 4))))
(display e)
(eval e (SCHEME-REPORT-ENVIRONMENT 5)))
prints: (EQ? 3/2 3/2)
and returns: #f

and: (let ((e (list 'eq? 3/2 3/2)))
(display e)
(eval e (SCHEME-REPORT-ENVIRONMENT 5)))
prints: (EQ? 3/2 3/2)
and can return either #t or #f depending on how the implementation
treats the literals 3/2 and 3/2.


> But even if it's done for efficiency, it must be some simple way
> to predict the behaviour. If not what's the use.

Just read the report! It's not even a multi-thousand page book like
the Common Lisp HyperSpec! Why don't you read the R5RS?

http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_idx_216

Eq? and eqv? are guaranteed to have the same behavior on symbols,
booleans, the empty list, pairs, procedures, and non-empty strings
and vectors. Eq?'s behavior on numbers and characters is
implementation-dependent, but it will always return either true or
false, and will return true only when eqv? would also return
true. Eq? may also behave differently from eqv? on empty vectors
and empty strings.


Since part of the behavior is implementation dependant, to be able to
predict their behavior you'd have to know the specific implementation.

--
__Pascal Bourguignon__ http://www.informatimago.com/

"You cannot really appreciate Dilbert unless you read it in the
original Klingon"
.



Relevant Pages

  • Re: Converting enums to pointers
    ... > You declare EMPTY to be a null pointer here. ... though it might be nice to use the extern keyword. ...
    (comp.lang.cpp)
  • Re: basic_string ctor
    ... > and a NULL pointer both construct a std::string as empty. ... than likely I'm converting something from a GUI layer to a standard ... as anything but an empty string. ...
    (microsoft.public.vc.stl)
  • Mouse Pointer Becomes 4-Way Arrow and Wont Revert
    ... In WinXP Home SP1, my mouse pointer occasionally becomes a 4-way arrow and ... will not revert to a regular pointer unless I go to the mouse properties ... PCI 1: Empty ... Firewall: Kerio Personal Firewall 2.1.4 ...
    (microsoft.public.windowsxp.help_and_support)
  • Re: futex question
    ... has an entry (lock held) in do_execveand return -EWOULDBLOCK to ... Same if pi_waiters is not empty. ... +#ifdef CONFIG_COMPAT ... Just because the head pointer has been registered does not mean that the list is non-empty. ...
    (Linux-Kernel)
  • Re: traverse linked list (Fortran 90)
    ... traverses and destroys a linked list. ... type, pointer:: h, t, c ... After next allocation c will point at another location but t still point at the preceeding location. ... Thus t%p => c will give the needed link from the preceeding node t to the new node c when the list is not empty. ...
    (comp.lang.fortran)