Я написал специальный генератор парсера, который создает код для преобразования старого и малоизвестного 7-битного набора символов в юникод. Вызов генератора парсера расширяется до группы defun
, заключенных в progn
, которые затем компилируются. Я хочу открыть только один из сгенерированных defun
s — верхний уровень — для остальной части системы; все остальные являются внутренними для синтаксического анализатора и вызываются только из динамической области действия анализатора верхнего уровня. Следовательно, другие сгенерированные defun
имеют неинтернированные имена (созданные с помощью gensym
). Эта стратегия отлично работает с SBCL, но недавно я впервые протестировал ее с CLISP и получил такие ошибки, как:
*** - FUNCALL: undefined function #:G16985
Кажется, что CLISP не может обрабатывать функции с неинтернированными именами. (Интересно, что система скомпилирована без проблем.) EDIT: кажется, что в большинстве случаев она может обрабатывать функции с неинтернированными именами. Смотрите ответ Рёрда ниже.
Мои вопросы: это проблема с CLISP или это ограничение Common Lisp, которое некоторые реализации (например, SBCL) преодолевают?
ИЗМЕНИТЬ:
Например, расширение макроса сгенерированной функции верхнего уровня (называемой parse
) имеет такое выражение:
(PRINC (#:G75735 #:G75731 #:G75733 #:G75734) #:G75732)
Вычисление этого выражения (путем вызова parse
) вызывает ошибку, подобную приведенной выше, даже несмотря на то, что функция определенно определена в том же раскрытии макроса:
(DEFUN #:G75735 (#:G75742 #:G75743 #:G75744) (DECLARE (OPTIMIZE (DEBUG 2)))
(DECLARE (LEXER #:G75742) (CONS #:G75743 #:G75744))
(MULTIPLE-VALUE-BIND (#:G75745 #:G75746) (POP-TOKEN #:G75742)
...
Два экземпляра #:G75735 определенно являются одним и тем же символом, а не двумя разными символами с одним и тем же именем. Как я уже сказал, это работает с SBCL, но не с CLISP.
ИЗМЕНИТЬ:
Пользователь SO Джошуа Тейлор указал, что это связано с давней ошибкой CLISP.
#:foo
, читатель создает новый символ, поэтому, например, вводя свой REPL, вы получаете(eq '#:foo '#:foo) ;=> nil
. Вы пытались вызвать функцию, введя ее имя? - person Joshua Taylor   schedule 03.10.2013gensym
только один раз и помещает результат в несколько мест расширения. Конечно, чтение расширения макроса приведет к созданию двух разных символов, но это не то, что происходит. - person nbtrap   schedule 03.10.2013case
выражений). - person nbtrap   schedule 03.10.2013gensym
, чтобы получить более читаемые макрорасширения. Это не должно повлиять на эту проблему, но может упростить ее отслеживание. - person Joshua Taylor   schedule 03.10.2013