[LISP] Ошибка в макросе
От: DSblizzard Россия  
Дата: 29.04.08 22:54
Оценка:
В следующем коде:

(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, но меня этот вариант не устраивает.
Программировать сложно. Но не программировать еще сложнее.
Re: [LISP] Ошибка в макросе
От: Turtle.BAZON.Group  
Дата: 30.04.08 05:33
Оценка: 10 (4)
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)) ; а тут вычислится


Вообще, резюмируя всё:


  1. В плане изучения лучше использовать Scheme;
  2. В плане чего-то реально делать всё то, что наделано — вряд ли годится, потому как setf по скорости ввода побыстрее =! будет, да и при обмене без гигиеничности можно нарваться на ситуацию, что перменная utemp окажется где-то определённой;
  3. Всё же, деструктивная модификация переменных не есть гуд и надо от этой идеологии пытаться уйти.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.