символ ключевого слова, заключенный в две трубы - PullRequest
4 голосов
/ 19 июня 2019

Предположим, функция fun в коде ниже, моя цель - оценить expr2 ниже.

(defun fun (&key (x nil)) x)
(defparameter expr1 (list 'fun :x 2))
(defparameter expr2 (list 'fun (intern "x" "KEYWORD") 2))

Как и ожидалось, (eval expr1) дает 2, но (eval expr2) выдает ошибку типа

*** - FUN: недопустимая пара ключевое слово / значение: | x |, 2 в списке аргументов. Допустимые ключевые слова: (: X) Доступны следующие перезапуски: ABORT: R1 Прервать основной цикл

Почему возникает эта ошибка? и как мне это исправить?

Ответы [ 2 ]

7 голосов
/ 19 июня 2019

Причина в том, что обычно в Common Lisp каждый символ при чтении преобразуется в заглавные буквы (это стандартное поведение и может быть изменено), так что:

(defun fun (&key (x nil)) x)
(defparameter expr1 (list 'fun :x 2))

фактически читается как:

(DEFUN FUN (&KEY (X NIL)) X)
(DEFPARAMETER EXPR1 (LIST 'FUN :X 2))

, в то время как intern получает строку в качестве первого параметра и не преобразует ее, так что в вашем примере "x" интернирован как символ :x, который отличается от символа :X (и это является причиной ошибки).Обратите внимание, что когда символ с строчными буквами печатается в REPL, он окружается символами канала (|), как в |x|, поэтому при повторном чтении строчные символы не изменяются:

CL-USER> :x
:X
CL-USER> :|x|
:|x|
CL-USER> (format t "~a" :|x|)
x
NIL

Чтобы решить вашу проблему, вы можете просто написать строку непосредственно в верхнем регистре:

(defparameter expr2 (list 'fun (intern "X" "KEYWORD") 2))

, а затем (eval expr2) работает как задумано.

5 голосов
/ 19 июня 2019

Обратите внимание, что \ и | являются управляющими символами в символах:

? 'foo\xBAR
FOO\xBAR

? '|This is a symbol|
|This is a symbol|

? ':|This is a keyword symbol with spaces and Capital letters!!!|
:|This is a keyword symbol with spaces and Capital letters!!!|

? 'what|? wow |this| also works|?
|WHAT? wow THIS also works?|
...