Я пропускаю какой-то важный факт об интернировании символов в LISP? - PullRequest
1 голос
/ 12 апреля 2011

Быть кратким. Вот несколько моих попыток интернировать и использовать символ в clisp.

 [1]> (setq sym (intern "foo"))
 |foo|
 [2]> (eq sym 'foo)
 NIL

Почему ???

 [3]> (defun internup (me &optional (package *package*))
   (intern (string-upcase me) package))
 INTERNUP

 [4]> (eq 'abc (internup "abc"))
 T

Вероятно, должно быть, upcase.

 [12]>(let ((abc 2))
   (eval '(+ 2 abc)))

 *** - EVAL: variable ABC has no value
 The following restarts are available:

OK

 [18]> (let ((abc 2))
 (eval '(+ 2 'abc)))

 *** - +: ABC is not a number
 The following restarts are available:

Интересно. Должен ли я установить его раньше.

 [14]> (setq a (internup "abc"))
 ABC

 [15]> (let ((abc 2))
 (eval '(+ 2 a)))

 *** - +: ABC is not a number
 The following restarts are available:

И снова неправильно. Хм, должно быть, я пропускаю важный факт об интернирующих символах в LISP. Вы можете мне помочь?

Ответы [ 3 ]

3 голосов
/ 12 апреля 2011

Ваша проблема не имеет никакого отношения к интернированию.

Первая проблема действительно связана с тем, что читатель всегда будет вводить символы в верхнем регистре, поэтому вам нужно вызвать (intern "FOO"), чтобы получить тот же результат, что и 'foo.

Проблема с EVAL вызвана тем, что LET вводит лексическое связывание, которое не видно внутри EVAL. Если вы действительно хотите, чтобы это работало, вам нужно объявить abc особенным, например:

(let ((abc 2))
    (declare (special abc))
    (eval '(1+ abc)))

Специальное объявление приведет к тому, что переменная будет иметь динамическое связывание вместо лексического связывания (последнее означает, что связывание ограничено локальным лексическим контекстом, т. Е. В форме LET. Со специальным объявлением переменная доступна для чего угодно что вызвано из этой формы).

Обратите внимание, что вы должны быть очень осторожны в использовании как специальных объявлений, так и eval, и вам, вероятно, следует сначала переосмыслить использование EVAL. Это очень редко, что вам действительно нужно использовать его. В большинстве случаев вы на самом деле ищете использование лямбда-функций.

3 голосов
/ 12 апреля 2011

Eval оценивает форму в нулевом лексическом окружении , т.е. без лексических привязок. Это не имеет ничего общего с интернированием символов.

2 голосов
/ 12 апреля 2011

Чувствительность к регистру для читателя Common Lisp определяется читаемой таблицей:

(readtable-case *readtable*)

Как правило, читатель изначально вводит символы в верхнем регистре (если вы явно не экранировали символы).Следовательно:

(eq (intern "foo") 'foo) => NIL

(eq (intern "FOO") 'foo) => T

(eq (intern "FOo") 'fo\o) => T

Вы можете использовать синтаксис обратной цитаты дляпостроить форму для eval:

(let ((abc 2))
  (eval `(+ 2 ,abc)))

=> 4

...