LINUX.ORG.RU

common lisp eval form

 , ,


0

2

Всем привет, а как можно сделать динамический binding в выражении, к примеру, чтобы выполнялся код наподобие

(let ((form '(+ a 1)))
  (let ((a 3))
     (eval form)))

Нужно здесь -

(defmacro cond-it (&body body)
  `(loop for (p clause) in ',body
	 for it = (eval p)
	 when it
	   do (let ()
		(declare (special it))
		(return (eval clause)))
	 finally (return nil)))

Если ты хочешь eval в макросе - ты хочешь не того.

vonenij
()

Емнип, стандартно никак.

Судя по докам, в Allegro CL есть функции для вычисления формы в определённом окружении, как и функции конструирования и дополнения окружений.

theNamelessOne ★★★★★
()

Ты хочешь cond?

Это делается так:

(defmacro my-cond (&rest forms)
  (labels ((gen-if (list)
                   (if list
                       (destructuring-bind (conditional action) (car list)
                         `(if ,conditional ,action ,(gen-if (cdr list)))))))
    (gen-if forms)))

eval в макросах - это моветон

vonenij
()

Ты anaphoric cond хочешь, что ли?

(defmacro aif (test then &optional else)
  `(let ((it ,test))
     (if it ,then ,else)))

(defmacro acond (&rest clauses)
  (if clauses
      `(aif ,(caar clauses)
            (progn ,@(cdar clauses))
            (acond ,@(cdr clauses)))))
theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Кстати, можно спросить, что означает умное слово «анафем^W anaphoric?

In linguistics, anaphora /əˈnæfərə/ is the use of an expression the interpretation of which depends upon another expression in context (its antecedent or postcedent).

В обычном cond тоже условие проверяется, если все условия до него не выполнены. Значит он тоже anaphoric шоле?

Как я понял, он хочет обычный cond (может, учится?) Логика такая: посмотрел в цикле все условия, первое удовлетворительное выполнил и вышел. Только делает всё не так

vonenij
()
Ответ на: комментарий от ados

Ах ты ж, я нашел про anaphoric macro. Оказывается, из-за it они так называются. Никогда бы не подумал, что для этого нужно такое сложное название

vonenij
()

Вообще-то можно. Только надо явно указать захватываемые биндинги:

> (let ((x 1))
    (pandoric-eval (x)
      '(+ 1 x)))
2

> let ((x 1))
    (pandoric-eval (x)
      '(incf x))
    x)

2

Исходники pandoric-eval на http://letoverlambda.com/lol.lisp

monk ★★★★★
()

anaphoric
pandoric

Взлолилоровал. sudo cast «мамкин борщ»

anonymous
()
Ответ на: комментарий от anonymous

Достаточно использовать гигиеническую макросистему.

Покажи, как сделать в Scheme:

(let ([i 1])
  (eval #'(+ i 1)))

i: identifier used out of context in: i

предложения?

monk ★★★★★
()
Ответ на: комментарий от theNamelessOne

что-то не очень понимаю, разве раскрытие макроса это не просто синтаксическая процедура? почему символы берутся из пакета, где объявлён макрос? и как тогда сделать, чтобы не писать в других пакетах helper::it, а просто it?

cl-user> (macroexpand-1 '(aif (+ 1 2) it))

(LET ((HELPER::IT (+ 1 2)))
  (IF HELPER::IT
      IT
      NIL))
T

SOLVED: ах ну да, просто экспортировать it, тупанул

pseudo-cat ★★★
() автор топика
Последнее исправление: pseudo-cat (всего исправлений: 1)
Ответ на: комментарий от monk

Я говорил не о евале, а о макросе, который нужен автору. Там евал не нужен, нужно уметь уметь погружать идентификатор в определенный лексический контекст.

anonymous
()
Ответ на: комментарий от pseudo-cat

почему символы берутся из пакета, где объявлён макрос?

Символы либо принадлежат пакету, либо они внепакетные. Внепакетные выглядят так: #:uninterned-symbol

Кстати, макросу loop пофиг на пакеты, так как он смотрит имя символа

vonenij
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.