В следующем коде:
(PROGN
(defmacro s-v (U)
`(symbol-value ,U))
(defmacro =! (&rest Args)
`(if (= (length ',Args) 2)
(setf (s-v (elt ',Args 0)) (eval (elt ',Args 1)))
(setf (elt (s-v (elt ',Args 0)) (eval (elt ',Args 1))) (eval (elt ',Args 2)))))
(defmacro obm (U1 U2)
`(let ((UTemp ,U1))
(=! ,U1 ,U2)
(=! ,U2 UTemp)))
(=! a 3)
(=! b 4)
(obm a b)
) ; PROGN
Возникает ошибка "EVAL: переменной UTEMP не присвоено значение". Как ее исправить? Можно заменить в 3-ем макросе =! на setf, но меня этот вариант не устраивает.
Программировать сложно. Но не программировать еще сложнее.
DS>Возникает ошибка "EVAL: переменной UTEMP не присвоено значение". Как ее исправить? Можно заменить в 3-ем макросе =! на setf, но меня этот вариант не устраивает.
Это всё потому что common lisp — очень уже перегруженный язык с кучей нюансов. И под одним именем у него может скрываться очень много всего. В том числе и символов. И переменных. И функций. При (elt '(b utemp) 1) значением приходит символ UTEMP, который не может быть вычислен, потому как у символа этого значения нет. Хотя у переменной есть. Чтобы пояснить, надо посмотреть на код.
(let ((utemp a)) (eval 'utemp)) ; не будет вычислено
(let ((utemp a)) (eval utemp)) ; будет вычислено в значение a
Поэтому вместо eval необходимо использовать symbol-value, но он не видит значения лексических переменных, объявленных в let. Для этого можно сделать небольшой хак.
(let ((utemp a)) (symbol-value 'utemp)) ; будет ошибка
(let ((utemp a)) (declare (special utemp)) (symbol-value 'utemp)) ; а тут вычислится
Вообще, резюмируя всё:
В плане изучения лучше использовать Scheme;
В плане чего-то реально делать всё то, что наделано — вряд ли годится, потому как setf по скорости ввода побыстрее =! будет, да и при обмене без гигиеничности можно нарваться на ситуацию, что перменная utemp окажется где-то определённой;
Всё же, деструктивная модификация переменных не есть гуд и надо от этой идеологии пытаться уйти.