Clojure 如何编写打印自己后缀的嵌套宏?
我正试图更好地理解。它是一个生成其他宏的宏(很像Clojure 1.4中基本数组函数的实现方式) 我想写一个宏,在运行时,它只打印生成的宏的后缀。i、 eClojure 如何编写打印自己后缀的嵌套宏?,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-
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