【问题标题】:Clojure macro problemClojure 宏问题
【发布时间】:2009-07-06 23:04:48
【问题描述】:

我正在尝试创建一个函数来创建一个以另一个结构为基础的新基础,作为开始,我尝试创建一个宏来创建一个具有与旧结构相同字段的新结构。我认为应该执行此操作的宏如下,但它给出了以下错误:

java.lang.Exception: Can't use qualified name as parameter: user/p1__132 

宏:

(defmacro prototype [structure obj]
  `(apply struct ~structure (map #(~obj %) (keys ~obj))))

使用示例:

(defstruct bintree :data :left :right)
(def a (struct bintree 3))
(prototype bintree a)

在这种情况下所需的输出是

{:data 3 :left nil :right nil}

【问题讨论】:

标签: clojure


【解决方案1】:

作为对您问题的评论发布的链接包含答案(罪魁祸首是处理匿名函数的参数的方式);以下使用 gensym 参数应该可以工作:

(defmacro prototype [structure obj]
  `(apply struct ~structure (map (fn [x#] (~obj x#)) (keys ~obj))))

【讨论】:

    【解决方案2】:

    这是一个固定版本:

    (defmacro prototype [structure obj]
      `(apply struct ~structure (map ~obj (keys ~obj))))
    

    为什么这需要是一个宏?一个函数也可以工作:

    (defn prototype [structure obj]
      (apply struct structure (map obj (keys obj))))
    

    为什么要复制结构?结构是不可变的,因此复制它们没有用。这个函数和上面的函数一样:

    (defn prototype [structure obj] obj)
    

    如果您想创建一个带有其他键和值的新结构,请使用assoc

    【讨论】:

      【解决方案3】:

      您不应该在宏中使用#()

      user> (macroexpand-1 `(foo #(bar %) baz))
      (user/foo (fn* [user/p1__2047] (user/bar user/p1__2047)) user/baz)

      fn* 表单的参数列表中没有命名空间限定符号。这就是你得到的错误。您应该避免在宏中使用这种特殊的阅读器语法,而应使用长格式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-16
        • 2015-11-16
        相关资源
        最近更新 更多