Reputation: 231
Racket document told me “eq?
return #t
if v1
and v2
refer to the same object”, but two fixnums
that are =
are also the same according to eq?
, =
“returns #t
if all of the arguments are numerically equal”. I can't find any message about “numbers” and “symbols”, but in the example I found :
> (eq? 'yes 'yes)
#t
This is contradictory to the above, because it was never mentioned above that symbol
was special, so 'yes
and 'yes
are not the same.
This one makes me even more confused :
> (eq? (expt 2 100) (expt 2 100))
#f
> (eq? (* 6 7) 42)
#t
if numbers are tested numerically, then (eq? (expt 2 100) (expt 2 100))
should return #t
, otherwise, numbers are tested by refer, then (eq? (* 6 7) 42)
should return #f
, so I guess both of the above situations are not right...
Why?!
Upvotes: 3
Views: 331
Reputation: 6502
This is to give additional information in addition to @Renzo's answer
how can I check if a data type is “internalized”
The answer is that it's complicated.
One factor is the reader:
Symbols, keywords, strings, byte strings, regexps, characters, and numbers produced by the reader in
read-syntax
mode are interned, which means that such values in the result ofread-syntax
are alwayseq?
when they areequal?
(whether from the same call or different calls toread-syntax
). Symbols and keywords are interned in bothread
andread-syntax
mode. Sending an interned value across a place channel does not necessarily produce an interned value at the receiving place. See alsodatum-intern-literal
anddatum->syntax
.
So (eq? (expt 2 100) (expt 2 100))
returns #f
because (expt 2 100)
is needed to be computed at runtime. On the other hand, (eq? 1267650600228229401496703205376 1267650600228229401496703205376)
returns #t
because the value is apparent at reading time, allowing Racket to intern the number.
Another factor is datatypes. For instance, a fixnum is always interned even if the value is not apparent at reading time, according to https://docs.racket-lang.org/reference/numbers.html
Two fixnums that are
=
are also the same according toeq?
. Otherwise, the result ofeq?
applied to two numbers is undefined
That means (eq? (+ 1 2) 3)
is guaranteed to be #t
.
A symbol is normally interned, but it's possible to make it uninterned via string->uninterned-symbol
and gensym
.
A symbol is like an immutable string, but symbols are normally interned, so that two symbols with the same character content are normally eq?.
The two procedures string->uninterned-symbol and gensym generate uninterned symbols, i.e., symbols that are not eq?, eqv?, or equal? to any other symbol, although they may print the same as other symbols.
So:
> (eq? (string->symbol "ab") (string->symbol (string-append "a" "b")))
#t
> (eq? (string->uninterned-symbol "ab") (string->uninterned-symbol "ab"))
#f
Upvotes: 4
Reputation: 27424
(expt 2 100)
is too big to be a fixnum
. Let's try to evaluate:
(expt 2 100) ; => 1267650600228229401496703205376
(fixnum? (expt 2 100)) ; => #f
(expt 2 10) ; => 1024
(fixnum? (expt 2 100)) ; => #t
This is because large numbers are allocated in several memory cells (think of them as a list of groups of digits).
On the other hand, each symbol, when read, is “internalized”. This means that the first time it is read, a new symbol value is created for it. Subsequently, when it is read again, the system checks if a symbol with that name is already present, and in this case the old symbol value is returned, without creating any new object in memory. So:
(eq 'yes 'yes) ; => #t
since what are apparently two different symbols with the same name are in effect the same object in memory.
Upvotes: 5