0

我最近发现,当我尝试使用(cadaddr (list 1 3 (list 5 7) 9)). 显然,默认情况下,Scheme 不允许在单函数形式中使用超过四个缩写的and调用的任何carand组合。我最初将此归咎于 Scheme 的极简主义,但后来我发现Common Lisp 也有这个缺陷cdrcarcdr

可以用宏解决吗?我们能否编写一个宏,在其调用中允许任意数量的aand并返回预期的结果,同时还具有与类似 Common Lisp 的宏的兼容性?如果不是,为什么不呢?如果是这样,是否曾经给出过理由,因为这不是我见过的任何 lisp 中的默认功能?dc[...]rsetf

4

1 回答 1

3

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

如邮件列表线程中所述,如果您想真正使用它,则必须解决一些错误。

于 2021-01-30T15:16:34.047 回答