英文:
Clojure: Take a macro metadata inside another macro
问题
在我其中一个宠物项目中,我有一堆宏,有时我想读取宏定义的元数据。原因是有时我的其他宏应该根据输入形式展开不同。当然,只是展开然后读取元数据更简单,但我想知道在宏正在展开时是否可能做到这一点。
考虑下面的宏:
(defmacro stackoverflow
{:example 23}
[& args]
(comment "This is just an example"))
在常规函数中从宏中读取元数据是非常简单的。
(defn- -example?
[form-var]
(-> form-var
meta
:example
some?))
:=> (-example? #'stackoverflow)
true
在另一个宏中做这个也不难:
(defmacro example?-macro[form]
`(-example? (var ~form)))
:=> (example?-macro stackoverflow)
true
但我找不到一种在宏展开时获取元数据的方法:
(defmacro test-example? [form]
(if (example?-macro form)
(println "It is indeed an example")
(println "It is not and example!")))
> Unable to resolve var: form in this context
我希望我的 test-example?
根据输入形式执行不同的工作,但找不到方法。
简而言之,整个问题 boils down to: How to take var from input macro inside macro without expanding like so:
;; 这是期望的行为
(defmacro imagining-solution
[form]
(if (:example `(meta (var ~form)))
(println "It is indeed an example")
(println "It is not and example!")))
;; 但这只能是梦想
英文:
On one of my pet projects I have a bunch of macros, and sometimes I want to be able to read metadata from macro definition. The reason being that sometimes my other macros should expand differently depending on input form. Of course, it is rather simpler to just expand and then read metadata, but I wonder if it's possible to do while macro is expanding.
Consider following macro:
(defmacro stackoverflow
{:example 23}
[& args]
(comment "This is just an example"))
It is perfectly simple to read metadata from macro in regular function.
(defn- -example?
[form-var]
(-> form-var
meta
:example
some?))
:=> (-example? #'stackoverflow)
true
It is not hard to do inside another macro as well:
(defmacro example?-macro[form]
`(-example? (var ~form)))
:=> (example?-macro stackoverflow)
true
But I couldn't find a way to get meta while macro is expanding:
(defmacro test-example? [form]
(if (example?-macro form)
(println "It is indeed an example")
(println "It is not and example!")))
> Unable to resolve var: form in this context
I want my test-example?
to do different job depending on the input form, but couldn't find a way to do it.
In short the whole question boils to: How to take var from input macro inside macro without expanding like so:
;; This is desired behaviour
(defmacro imagining-solution
[form]
(if (:example `(meta (var ~form)))
(println "It is indeed an example")
(println "It is not and example!")))
;; But one can only dream about
答案1
得分: 0
立刻在发布这个问题后 在这里找到了解决方案:https://stackoverflow.com/questions/30679637/accessing-arguments-metadata-in-clojure-macro?rq=2
只需使用 resolve
函数!
英文:
Immediately after posting this question found a solution here:
https://stackoverflow.com/questions/30679637/accessing-arguments-metadata-in-clojure-macro?rq=2
Just use resolve
function!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论