Why should (symbol=? 'a (string->uninterned-symbol "a"))
return #f
? ~I can understand why they are not equal?
.~ What is the idiomatic way to compare symbols which may be uninterned?
A symbol is an object (value) which has an address in the store and contains an array of characters with its name. When (string->symbol "a")
is called a table containing all existing symbols are consulted. If a symbol containing the string “a” is the table, then that symbols is returned. On the other hand (string->uninterned-symbol "a")
doesn’t consult the table. It simply creates a new symbol in memory containing the name a. Since it is a new value it has a different address than all other symbols.
The comparison eq?
compares (roughtly) the address of two values, so an interned symbol and an uninterned symbol are not eq?
since they have different addresses.
The same reasoning explains why (eq? (string->uninterned-symbol "a")) (string->uninterned-symbol "a")))
returns false.
Normally a symbol is uninterned only if one want a unique object not eq?
to any other symbol.
If you want to compare the names of two symbols, you can use (string-equal? (symbol->string s1) (symbol->string s2))
.
But that suggests that strings should have been used rather than symbols.
Thanks for the explanation. I understand some of the issues with interned strings, performance of equality checking is one motivation for them.
But since (eq? string0 string1)
is #f
for strings with the same content but different locations and (string=? string0 string1)
is #t
, I reasoned that symbols would behave similarly. I assumed wrong.
I solved my problem by sticking with string->symbol
over string->uninterned-symbol
, FYI.
Thanks for the help :slightly_smiling_face:.
@aymano.osman I recommend using only interned symbols. It’s less confusing that way.
Thanks, I will do that.