是否可以使用宏来与任意数量的汽车和 cdr 调用(例如 cadaddr)进行 c[...]r 组合?
Can a macro be used to make c[...]r combinations with any arbitrary number of car and cdr calls, such as cadaddr?
我最近发现当我尝试使用 (cadaddr (list 1 3 (list 5 7) 9))
时,我所有的 Scheme 实现都会抛出错误。显然,默认情况下,Scheme 不允许在单函数形式中使用超过四个缩写的 car
和 cdr
调用的任何 car
和 cdr
组合。我最初将此归咎于 Scheme 的极简主义,但后来我发现 Common Lisp also shares this defect.
这个可以用宏解决吗?我们能否编写一个宏,在其 c[...]r
调用中允许任意数量的 a
和 d
以及 returns 预期结果,同时还具有与 Common Lisp 类似的兼容性像 setf
这样的宏?如果不是,为什么不呢?如果是这样,有没有给出一个理由,因为这不是我见过的任何 lisp 中的默认功能?
Let Over Lambda for 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 [& 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
如邮件列表线程中所述,如果您想真正使用它,则必须解决一些错误。
我最近发现当我尝试使用 (cadaddr (list 1 3 (list 5 7) 9))
时,我所有的 Scheme 实现都会抛出错误。显然,默认情况下,Scheme 不允许在单函数形式中使用超过四个缩写的 car
和 cdr
调用的任何 car
和 cdr
组合。我最初将此归咎于 Scheme 的极简主义,但后来我发现 Common Lisp also shares this defect.
这个可以用宏解决吗?我们能否编写一个宏,在其 c[...]r
调用中允许任意数量的 a
和 d
以及 returns 预期结果,同时还具有与 Common Lisp 类似的兼容性像 setf
这样的宏?如果不是,为什么不呢?如果是这样,有没有给出一个理由,因为这不是我见过的任何 lisp 中的默认功能?
Let Over Lambda for 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 [& 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
如邮件列表线程中所述,如果您想真正使用它,则必须解决一些错误。