Clojure 如何编写打印自己后缀的嵌套宏?

Clojure 如何编写打印自己后缀的嵌套宏?,clojure,macros,Clojure,Macros,我正试图更好地理解。它是一个生成其他宏的宏(很像Clojure 1.4中基本数组函数的实现方式) 我想写一个宏,在运行时,它只打印生成的宏的后缀。i、 e user=> (nested-macro joe) user=> (nested-macro-named-joe) hello from joe nil 我很难做到这一点 以下是我尝试过的: 尝试1 (defmacro nested-macro [name] `(defmacro ~(symbol (str "nested-

我正试图更好地理解。它是一个生成其他宏的宏(很像Clojure 1.4中基本数组函数的实现方式)

我想写一个宏,在运行时,它只打印生成的宏的后缀。i、 e

user=> (nested-macro joe)
user=> (nested-macro-named-joe)
hello from joe
nil
我很难做到这一点

以下是我尝试过的:

尝试1

(defmacro nested-macro [name]
  `(defmacro ~(symbol (str "nested-macro-named-" name))
     []
     `(println "hello from " ~name)))
输出:

hello from#

尝试2

(defmacro nested-macro [name]
  (let [local-name name]
    `(defmacro ~(symbol (str "my-custom-macro-named-" ~local-name))
       []
       `(println "hello from " ~local-name))))
错误

试图调用unbound fn的非法状态异常:#'clojure.core/unquote clojure.lang.Var$unbound.throwArity(Var.java:43)

尝试3:

(defmacro nested-macro [name]
  (let [local-name name]
    `(defmacro ~(symbol (str "nested-macro-named-" name))
       []
       `(println "hello from " ~(symbol local-name)))))
编译器错误:

compilereException java.lang.RuntimeException:没有这样的变量:joy.dsl/local name

为了方便起见,我还尝试将
#
添加到局部变量中,结果与上面类似,但使用了“auto”名称,例如
local-name\uuuu 1127\uuu auto\uuuu
,但我不认为这是解决方案的一部分


我怎样才能做到这一点

要知道宏出了什么问题,我总是使用
macroexpand-1

从您的第一个示例:

(macroexpand-1 '(nested-macro joe))
结果:

(clojure.core/defmacro nested-macro-named-joe [] 
  (clojure.core/seq 
    (clojure.core/concat 
      (clojure.core/list (quote clojure.core/println)) 
      (clojure.core/list "hello from ") 
      (clojure.core/list clojure.core/name))))
如果查看最后一个参数,就会发现您使用的是clojure.core/name,这可能不是您想要的,因为您实际上需要名为“name”的参数

要修复它,只需在
name
param中添加另一个unquote,但由于name param实际上是一个符号,您真正想要的是获得它的名称,如中所示:

(defmacro nested-macro [the-name]
  `(defmacro ~(symbol (str "nested-macro-named-" the-name))
     []
     `(println "hello from " ~~(name the-name))))

“~~name
是在类似情况下引用的一种更通用的解决方案-您并不总是乐于获得值的字符串表示形式。将~~(name)替换为“~~name会导致
编译器异常java.lang。RuntimeException:无法解析符号:joe在此上下文中,编译:(无源代码路径:1)
。啊,嵌套引用很难。我想是
'~'~name
阻止内部宏尝试解析名称。谢谢,我想我现在理解了嵌套引用。下一步:
&env
&form