请在2024 Clojure 状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解更多关于此功能的信息。

0
Clojure
编辑

假设我要编写一个可以创建具有:tag元数据属性列表(例如Java类型提示)的宏,针对给定的符号向量。考虑以下REPL会话

(def ^String x nil)
(def ^Integer y nil)
(def ^Long z nil)
(defmacro all-tags [items]
   (vec (for [item items]
      `(:tag (meta (resolve (quote ~item)))))))

; this works fine
(all-tags [x y z])
[java.lang.String java.lang.Integer java.lang.Long]

; however, if I instead have a symbol that refers to this list, it fails
(def myargs [x y z])
(all-tags myargs)
Syntax error macroexpanding all-tags at (form-init2442452721395147632.clj:1:1).
Don't know how to create ISeq from: clojure.lang.Symbol

如何重写all-tags宏以处理第二种情况,使其与第一种情况返回相同的结果?

1 个回答

+2

选定
 
最佳答案

所以,当你这样做的时候

(def myargs [x y z])

xyz已被评估---myargs[nil nil nil]---因此获取符号/变量的元数据将会困难。

这是一个没有宏版本的类似实现

> (def ^String x nil)
#'x
> (def ^Integer y nil)
#'y
> (def ^Long z nil)
#'z
> x
nil
> y
nil
> z
nil
> (defn all-tags [items]
    (map (comp :tag meta resolve) items))
#'all-tags
> (all-tags '[x y z])
(java.lang.String java.lang.Integer java.lang.Long)
> (def myargs '[x y z])
#'myargs
> (all-tags myargs)
(java.lang.String java.lang.Integer java.lang.Long)
非常感谢;非常感激这段示例代码!
当然!我也学到一些东西。(
...