eq? of quoted expressions

46 views
Skip to first unread message

wanderley...@gmail.com

unread,
Oct 25, 2019, 10:35:09 AM10/25/19
to Racket-Users List
Why (eq? (quote a) (quote a)) is #t but (eq? (quote (a)) (quote (a)))
is #f? I would expect that if (quote (a)) was a mutable pair but it
is not since (quote (a)) returns #f. It seems that guile returns #t
as I was expecting.

Sage Gerard

unread,
Oct 25, 2019, 12:28:14 PM10/25/19
to wanderley...@gmail.com, Racket-Users List
By https://docs.racket-lang.org/reference/symbols.html, Two interned symbols are eq? to each other.

But in the other example, you are comparing two lists each containing a single symbol. A new list is created in each expression, and eq? is comparing the object references and not the content. For comparison (let ([l (quote a)]) (eq? l l)) evaluates to #t

~slg

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> You received this message because you are subscribed to the Google Groups "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/CAAmHZof2uu7hkU4eMNz510UFOX4Pn5RUhj08_zHobqCcshdhug%40mail.gmail.com.


Alexis King

unread,
Oct 25, 2019, 12:28:37 PM10/25/19
to wanderley...@gmail.com, Racket-Users List
Unlike eq? on symbols, eq?’s behavior on quoted lists is unspecified, so I do not think there is a significantly deeper reason than “that isn’t what the current implementation chooses to do.” Whether the answer is #t or #f could change tomorrow, on a different VM, on a different architecture, or on Friday the 13th.

Is there a reason you would like the answer to be #t?

Sage Gerard

unread,
Oct 25, 2019, 12:29:29 PM10/25/19
to wanderley...@gmail.com, Racket-Users List
Typo: Meant (let ([l (quote (a))]) (eq? l l))


~slg

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Friday, October 25, 2019 12:28 PM, Sage Gerard <sa...@sagegerard.com> wrote:

> By https://docs.racket-lang.org/reference/symbols.html, Two interned symbols are eq? to each other.
>
> But in the other example, you are comparing two lists each containing a single symbol. A new list is created in each expression, and eq? is comparing the object references and not the content. For comparison (let ([l (quote a)]) (eq? l l)) evaluates to #t
>
> ~slg
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> On Friday, October 25, 2019 10:34 AM, wanderley...@gmail.com wanderley...@gmail.com wrote:
>
> > Why (eq? (quote a) (quote a)) is #t but (eq? (quote (a)) (quote (a)))
> > is #f? I would expect that if (quote (a)) was a mutable pair but it
> > is not since (quote (a)) returns #f. It seems that guile returns #t
> > as I was expecting.
> >

David Thrane Christiansen

unread,
Oct 25, 2019, 12:35:04 PM10/25/19
to wanderley...@gmail.com, racket users
Hello,

eq? decides object identity, or pointer equality. Symbols are interned, which means that there's a table mapping symbol names to underlying objects, such that using the name twice results in the same allocated symbol object being returned.

Pairs are not interned. Each time a new pair is constructed, a new object with its own identity comes into existence. Lists are built from pairs, so these objects are separate.

I'm not sure why Guile returns #t for this. If pairs are mutable there, then it could lead to aliasing problems. On the other hand, there's a long tradition of being skeptical of using list structure that results from quote when aliasing and identity matter, because quote returns its argument directly and the reader can do unpredictable things in those contexts with respect to identity. My guess is that Guile's reader is reusing list structure, which you're observing.

David

--

Alexis King

unread,
Oct 25, 2019, 12:38:26 PM10/25/19
to David Thrane Christiansen, wanderley...@gmail.com, racket users
> On Oct 25, 2019, at 11:34, David Thrane Christiansen <da...@davidchristiansen.dk> wrote:
>
> I'm not sure why Guile returns #t for this. If pairs are mutable there, then it could lead to aliasing problems.

The Scheme standard has historically left the behavior of mutation on quoted values unspecified to permit precisely this kind of implementation decision (but it does not require any particular behavior). I would imagine Guile makes quoted pairs immutable even if other pairs are mutable.

Jens Axel Søgaard

unread,
Oct 25, 2019, 1:12:43 PM10/25/19
to wanderley...@gmail.com, Racket-Users List

Racket (and Scheme) interns symbol literals. That is, if you put the literal '(foo foo) in your code
you will get a list value of length two, its elements are both the same symbol spelled foo.
On the other hand in Scheme '("foo" "foo") will get you a list value of length two. The
elements of the lists are two strings, which may or may not be the same string (since strings
are neither guaranteed to be interned (nor not to be interned) in Scheme). 

If the same literal appears twice in the source code some Scheme implementations
will use the same value twice. So in '(foo) '(foo) the two list literals may or may not
return the same value. List values aren't guaranteed to be interned, so
(eq? '(foo) '(foo)) may or may not return true in a Scheme implementation.

Note that this explains why Schemers write

    (define magic (list 'magic))

and not

  (define magic '(magic))

in order to obtain a unique value, not eq? to any other value.

In order to allowing implementations to share values in literals in R5RS it is unspecified
what happens when you mutate a literal. 

/Jens Axel


wanderley...@gmail.com

unread,
Oct 25, 2019, 1:27:48 PM10/25/19
to Alexis King, Racket-Users List
On Fri, Oct 25, 2019 at 9:28 AM Alexis King <lexi....@gmail.com> wrote:
Unlike eq? on symbols, eq?’s behavior on quoted lists is unspecified, so I do not think there is a significantly deeper reason than “that isn’t what the current implementation chooses to do.” Whether the answer is #t or #f could change tomorrow, on a different VM, on a different architecture, or on Friday the 13th.

Is there a reason you would like the answer to be #t?
Not strong one.  I was implementing a compiler (to a computer simulator that I did) and I wanted to express some of my constants as list (because it would make easier to read them in case expression).  I switched to use match instead.

My intuition was that two quoted list of constant values would eq?.



> On Oct 25, 2019, at 09:34, wanderley...@gmail.com wrote:
>
> Why (eq? (quote a) (quote a)) is #t but (eq? (quote (a)) (quote (a)))
> is #f?  I would expect that if (quote (a)) was a mutable pair but it
> is not since (quote (a)) returns #f.  It seems that guile returns #t
> as I was expecting.

--
Abraço,
Wanderley Guimarães

Philip McGrath

unread,
Oct 25, 2019, 1:49:06 PM10/25/19
to wanderley...@gmail.com, Alexis King, Racket-Users List
On Fri, Oct 25, 2019 at 1:27 PM wanderley...@gmail.com <wanderley...@gmail.com> wrote:
On Fri, Oct 25, 2019 at 9:28 AM Alexis King <lexi....@gmail.com> wrote:
Unlike eq? on symbols, eq?’s behavior on quoted lists is unspecified …

Is there a reason you would like the answer to be #t?
Not strong one.  I was implementing a compiler (to a computer simulator that I did) and I wanted to express some of my constants as list (because it would make easier to read them in case expression).  I switched to use match instead.

Note that Racket's `case` (unlike the R5RS or R6RS versions) is based on `equal?`, so the expression:
(case (list 'a)
  [((a))
   "ok"]
  [else
   #f])
reliably produces `"ok"`.

Also, as you very well may know, the left-hand side of a `case` clause isn't an implicitly-quoted list expression: it's a parenthesized sequence of implicitly-quoted expressions. I mention this because, often, you might represent a constant as a symbol. If you use a case expression to, in logical terms, test if some value is a member of a "list" of constant symbols, there aren't actually any Racket list values involved.

It's often a good choice to use `match` rather than `case`, since `match` is more flexible and extensible. However, `match` doesn't provide `case`'s guarantee of O(log N) performance, which can be important if you are generating very large case expressions.

-Philip
Reply all
Reply to author
Forward
0 new messages