#lisp #symbols
#lisp #символы
Вопрос:
Если быть кратким. Вот мои несколько попыток интернировать и использовать символ в clisp.
[1]> (setq sym (intern "foo"))
|foo|
[2]> (eq sym 'foo)
NIL
Почему???
[3]> (defun internup (me amp;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:
ОК
[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. Вы можете мне помочь?
Комментарии:
1.
(setf (symbol-value a) 2)
будет установлено'ABC
значение2
.
Ответ №1:
Ваша проблема не имеет ничего общего с интернированием.
Первая проблема действительно вызвана тем фактом, что считыватель всегда будет использовать символы верхнего регистра, поэтому вам нужно вызвать (intern «FOO»), чтобы получить тот же результат, что и ‘foo.
Проблема с EVAL вызвана тем фактом, что LET вводит лексическую привязку, которая не видна внутри EVAL. Если вы действительно хотите, чтобы это сработало, вам нужно было бы объявить abc специальным, вот так:
(let ((abc 2))
(declare (special abc))
(eval '(1 abc)))
Специальное объявление приведет к тому, что переменная будет иметь динамическую привязку вместо лексической привязки (последнее означает, что привязка ограничена локальным лексическим контекстом, то есть в форме LET. С помощью специального объявления переменная доступна для всего, что вызывается из этой формы).
Обратите внимание, что вам следует быть очень осторожным с использованием как специальных объявлений, так и eval, и вам, вероятно, в первую очередь следует пересмотреть свое использование EVAL. Очень редко вам действительно нужно это использовать. В большинстве случаев вы на самом деле ищете использование лямбда-функций вместо этого.
Комментарии:
1. Большое вам спасибо. Но что именно вы имеете в виду под использованием лямбда-функции. Я работаю над mathematical symbolic evaluator и не могу представить иной подход, чем вызов функции eval. (eval (diff (make-equation database) ‘x))
2. EVAL вычислит выражение в нулевой лексической среде. LET (обычно) устанавливает лексические привязки. Итак, чтобы получить доступ к переменной из EVAL, это должна быть динамическая привязка, поэтому потребуется либо специальное объявление для привязки, либо объявление, установленное DEFVAR или DEFPARAMETER .
Ответ №2:
Eval
оценивает форму в нулевой лексической среде, то есть без лексических привязок. Это не имеет никакого отношения к интернированию символов.
Ответ №3:
Чувствительность Common Lisp Reader к регистру определяется таблицей чтения:
(readtable-case *readtable*)
Обычно читатель изначально вводит символы в верхнем регистре (если вы явно не экранируете символы). Следовательно:
(eq (intern "foo") 'foo)
=> НОЛЬ
(eq (intern "FOO") 'foo)
=> T
(eq (intern "FOo") 'foo)
=> T
Вы можете использовать синтаксис обратных кавычек для построения формы для eval:
(let ((abc 2))
(eval `( 2 ,abc)))
=> 4
Комментарии:
1.Просто для пояснения: эта форма обратной кавычки эквивалентна
(list (quote ) (quote 2) abc)
, которая соответствует списку( 2 2)
, который затем передаетсяeval
. Явныйeval
вызов никогда не видит переменнуюabc
.