定义一个使用^{}元数据语法的宏



我想定义一个这样的宏:

(defmacro foo-macro
  "[name] is the name of the function to define
   [meta-data] is the map that defines the meta-data of the function"
  [name meta-data]
  (let [vals (gensym "label-")]
    `(def ~name
       ^@~meta-data
       (fn [~vals] (eval nil)))))

然而,我得到这个编译错误:

未处理java.lang.IllegalArgumentException元数据必须是符号、关键字、字符串或映射

我认为这是正常的。然而,我不确定我如何才能使这样的宏工作,或者如果它甚至是可能的。

注意:我不想使用with-meta 。阅读其他问题的解决方案的修订版,以理解为什么:Clojure:在循环上下文中获取函数的符号存在问题。

我使用with-meta的唯一原因是,如果你有一种方法使它返回一个非afunc标识符

我很抱歉,但是你确实想使用with-meta,你只是想在你的宏中使用它,而不是在你返回的代码中。

你通过阅读^{:foo :bar} (fn [])得到的形式与你通过评估(with-meta `(fn []))得到的形式大致相同,所以这就是你想在宏中做的:在生成代码时评估with-meta调用。

(defmacro foo-macro
  "[name] is the name of the function to define
   [meta-data] is the map that defines the meta-data of the function"
  [name meta-data]
  (let [vals (gensym "label-")]
    `(def ~name
       ~(with-meta `(fn [~vals] (eval nil))
          meta-data))))

调用(foo-macro fn-name {:foo "bar"})应该给你你想要的:一个(meta fn-name)返回{:foo "bar"}的函数,当打印时,输出类似#<user$fn_name user$fn_name@35df85a1>的东西。

最新更新