How do I convert a string to a symbol for use as a key in the Lisp "assoc" function?
Asked Answered
J

2

5

I have this association-list in Common Lisp:

(defvar base-list (list (cons 'a 0) (cons 2 'c)))

I have to call assoc when my argument is of type string.

For the pair (A . 0) I have to convert "a" to a symbol, and for the pair (2 . C) I have to convert "2" to a symbol. How can I do that?

This should work like this:

CL-USER 28 : 1 > (assoc (convert-string-to-symbol "a") base-list)
(A . 0)
CL-USER 28 : 1 > (assoc (convert-number-to-symbol "2") base-list)
(2 . C)

I tried using intern but got NIL:

CL-USER 29 : 1 > (assoc (intern "a") base-list)
NIL
Jordanjordana answered 17/6, 2012 at 11:33 Comment(3)
Hmm..this is similar but doesn't work!! #9812893Jordanjordana
get out of the debugger.Lewison
The NUMBER-TO-SYMBOL part makes no sense, since the number 2 is no symbol.Lewison
S
5

You were close with intern; you just had the case wrong. Try this:

> (assoc (intern "A") base-list)
(A . 0)

Note that here the name-as-string is capitalized.

Alternately, you could use find-symbol to look for an existing symbol by name:

> (assoc (find-symbol "A") base-list)
(A . 0)

The key here is that when you wrote your original defvar form, the reader read the string "a" and—by virtue of the current readtable case—converted the symbol name to be uppercase. Symbols with names of different case are not equal. It just so happens that at read time the reader is projecting what you wrote (lowercase) to something else (uppercase).

You can inspect the current case conversion policy for the current reader using the readtable-case function:

> (readtable-case *readtable*)
:UPCASE

To learn more about how the readtable case and the reader interact, see the discussion in section 23.1.2 of the Hyperspec.

Shew answered 17/6, 2012 at 13:44 Comment(0)
S
15

The function you want is called read-from-string:

CL-USER> (read-from-string "a")
A
1
CL-USER> (read-from-string "2")
2
1
CL-USER> 

Note that solutions based on using intern or find-symbol would not work for strings representing numbers (e.g., "2") on most implementations.

Swatch answered 31/1, 2018 at 4:11 Comment(0)
S
5

You were close with intern; you just had the case wrong. Try this:

> (assoc (intern "A") base-list)
(A . 0)

Note that here the name-as-string is capitalized.

Alternately, you could use find-symbol to look for an existing symbol by name:

> (assoc (find-symbol "A") base-list)
(A . 0)

The key here is that when you wrote your original defvar form, the reader read the string "a" and—by virtue of the current readtable case—converted the symbol name to be uppercase. Symbols with names of different case are not equal. It just so happens that at read time the reader is projecting what you wrote (lowercase) to something else (uppercase).

You can inspect the current case conversion policy for the current reader using the readtable-case function:

> (readtable-case *readtable*)
:UPCASE

To learn more about how the readtable case and the reader interact, see the discussion in section 23.1.2 of the Hyperspec.

Shew answered 17/6, 2012 at 13:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.