#macros #scheme #lisp #common-lisp #cdr
#макросы #схема #шепелявый #common-lisp #cdr
Вопрос:
Недавно я обнаружил, что все мои реализации Scheme выдают ошибку при попытке использования (cadaddr (list 1 3 (list 5 7) 9))
. По-видимому, по умолчанию схема не допускает никаких car
cdr
комбинаций and в однофункциональной форме, которые используют более четырех сокращенных car
cdr
вызовов and. Первоначально я винил в этом минимализм Scheme, но затем обнаружил, что Common Lisp также разделяет этот недостаток.
Можно ли это решить с помощью макроса? Можем ли мы написать макрос, который допускает произвольное количество a
и d
в своих c[...]r
вызовах и возвращает ожидаемый результат, а также имеет совместимость с Common Lisp-подобными макросами, такими как setf
? Если нет, то почему бы и нет? И если да, была ли когда-либо указана причина, по которой это не является функцией по умолчанию ни в одном lisp, который я видел?
Ответ №1:
Такой макрос описан в разделе Let Over Lambda для common lisp. Вы должны обернуть свой код с (with-cxrs ...)
помощью, чтобы включить их все в область видимости, но он просматривает ваш код, чтобы увидеть, какие комбинаторы вам нужны. Я написал его порт на Clojure много лет назад для развлечения, хотя, конечно, никто (включая меня) никогда не хотел использовать его по-настоящему. Вы могли бы перенести его в Scheme, если хотите.
(defn cxr-impl [name]
(when-let [op (second (re-matches #"c([ad] )r" name))]
`(comp ~@(map {a `first d `rest} op))))
(defmacro with-cxrs [amp; body]
(let [symbols (remove coll? (tree-seq coll? seq body))]
`(let [~@(for [sym symbols
:let [impl (cxr-impl (name sym))]
:when impl
thing [sym impl]]
thing)]
~@body)))
user> (macroexpand-1 '(with-cxrs (inc (caadaaddadr x))))
(let [caadaaddadr (comp first first rest first first rest rest first rest)]
(inc (caadaaddadr x)))
https://groups.google.com/g/clojure/c/CanBrJPJ4aI/m/S7wMNqmj_Q0J
Как отмечалось в ветке списка рассылки, есть некоторые ошибки, которые вам придется устранить, если вы хотите использовать это по-настоящему.