Ни функция, ни макрос не подойдут

Задумайтесь над этим вопросом. Здесь основной проблемой является код:

(progv '(op arg) '(1+ 1)
 (eval '(op arg)))

Проблема здесь в том, что progv привязывает значение к переменной как переменную symbol-value не symbol-function, Но это очевидно, потому что мы не предложили явно, какие значения являются функциями.


План

Итак, чтобы решить эту проблему, я подумал о том, чтобы вручную динамически связывать переменные с их значениями в зависимости от типа значений. Если значения fboundp тогда они должны быть связаны с symbol-function переменной. Ограничение в том, что match-if не может быть macro, Это должно быть functionпотому что это называется funcall,

Макрос:functioner:

(defmacro functioner (var val)
  `(if (and (symbolp ',val)
            (fboundp ',val))
       (setf (symbol-function ',var) #',val)
       (setf ,var ,val)))

Функция:match-if:

(defun match-if (pattern input bindings)
  (eval `(and (let ,(mapcar #'(lambda (x) (list (car x))) bindings)
                (declare (special ,@ (mapcar #'car bindings)))
                (loop for i in ',bindings
                      do (eval `(functioner ,(first i) ,(rest i))))
                (eval (second (first ,pattern))))
              (pat-match (rest ,pattern) ,input ,bindings))))

Здесь let Часть объявляет все переменные лексически (предположительно). затем declare объявляет их special, затем functioner удачно связывает переменные и их значения. Затем код в шаблоне оценивается. Если часть кода истинна, то только функция сопоставления с образцом pat-match вызывается.


Эта проблема

Проблема в том, что в функции оцениваются все ее аргументы. таким образом bindings в let а также declare запчасти будут заменены на что-то вроде:
((v1 . val1)(v2 . val2)(v3 . val3))
не
'((v1 . val1)(v2 . val2)(v3 . val3))
Таким образом, это рассматривается как код, а не как список.
Итак, я застрял здесь. И макросы не помогут мне в этом.
Любая помощь приветствуется.

1 ответ

Решение

Не ответ, который вы ищете, но PROGV специальный оператор; ему предоставляется возможность изменять динамические привязки переменных во время выполнения; AFAIK, вы не можете просто взломать его для работы с "динамическими привязками функций". Точка progv заключается в использовании списка символов и значений, которые оцениваются, что означает, что вы можете генерировать символы во время выполнения и динамически связывать их с соответствующими значениями.

Вы можете найти решение с eval но учтите, что если вы макрорасширитесь в (eval ...)затем вы теряете окружающий лексический контекст, который обычно не тот, который вы хотите ("eval" работает в нулевой лексической среде). Я предполагаю, что у вас также может быть пользовательский обходчик кода, который работает с формами верхнего уровня, но реорганизует их, когда находит ваш специальный оператор, чтобы вернуть контекст обратно, производя что-то вроде (eval '(let (...) ...)),

Другие вопросы по тегам