Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros Clojure宏扩展_Macros_Clojure_Lisp - Fatal编程技术网

Macros Clojure宏扩展

Macros Clojure宏扩展,macros,clojure,lisp,Macros,Clojure,Lisp,我正在研究一个宏,我试图找出如何避免某些形式的扩展,以下面的和宏为例 (defmacro and ([] true) ([x] x) ([x & next] `(let [and# ~x] (if and# (and ~@next) and#)))) 扩大后, (mexpand-all '(and 1 2 3)) 变成 (let* [and__973__auto__ 1] (if and__973__auto__ (let* [a

我正在研究一个宏,我试图找出如何避免某些形式的扩展,以下面的和宏为例


(defmacro and
  ([] true)
  ([x] x)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))
扩大后,

(mexpand-all '(and 1 2 3))
变成


(let* [and__973__auto__ 1]
      (if and__973__auto__
        (let* [and__973__auto__ 2]
              (if and__973__auto__ 3 and__973__auto__))
        and__973__auto__))

在这种情况下,我需要做的是阻止let扩展到let*

哈?不清楚“停止”
let
扩展是什么意思
let
是clojure.core中定义的宏,编译器对此一无所知:它只理解
let*
。如果宏扩展为一个
let
,而它(不知何故)拒绝进一步扩展,则它将无法编译


如果只想单独检查宏的输出,而不必担心递归扩展,则应使用
macroexpand
macroexpand-1
而不是使用此
mexpand all
功能。我不知道
mexpand all
从何而来,但当我需要类似的东西时,我会使用
clojure.walk/macroexpand all

使用
macroexpand-1
执行单级宏扩展

加载
宏后,此表达式:

user=> (macroexpand-1 '(and 1 2 3))
收益率:

(clojure.core/let [and__1__auto__ 1] (if and__1__auto__ (clojure.core/and 2 3) and__1__auto__))

递归宏扩展的工作原理是反复扩展窗体,直到没有宏可扩展为止。这意味着,如果要递归地展开宏,但忽略某些表单,则必须编写自己的自定义扩展程序,或者查找其他人的自定义扩展程序

下面是一个简单的例子:

(defn my-expander [form]
    (cond (not (list? form)) (mexpand-1 form)
        (= (first form) 'let) form
           :else (map my-expander (mexpand-1 form))))
如果我犯了任何错误,请原谅我。我在Scheme和CL方面比Clojure强得多

--编辑--
请注意,上面的函数也不会展开let语句的子窗体。

我试图做的是递归展开除let窗体之外的所有内容。顺便说一句,mexpand也来自contrib宏utilsI,我试图阻止某些形式的扩展。我想解释一下为什么这个问题有权存在。在我的例子中,我尝试使用clojure宏扩展作为从非clojure lisp到另一个非clojure lisp的传输程序。它工作得相当好,除了一些源lisp语法与clojure的内置宏冲突的情况。