如何在运行时类型依赖时简化那些拖动宏?

时间:2013-08-13 09:24:34

标签: macros clojure case

人, 先看一下代码:

(defmacro map-remove- [v w]
  `(dosync
     (ref-set ~v (dissoc @~v (keyword ~w)))))
(defmacro set-remove- [v w]
  `(dosync
     (ref-set ~v (disj @~v ~w))))
(defmacro clean- [v] 
  `(dosync
    (ref-set ~v (empty @~v))))

它们现在工作正常,但我想写一个更通用的宏来将“map-remove-”和“set-remove-”结合在一起。根据我的C / Java经验,我选择了“case”,但显然情况不能用于宏定义导致“测试常量未被评估。它们必须是编译时文字”,以下代码将不起作用:< / p>

(defmacro [x]
  (case (type x) ;;;;;;;;;;; This will never work!directly reach to default clause 
    ....)) 

有人有什么建议吗?非常感谢。

1 个答案:

答案 0 :(得分:1)

您可以使用函数map?set?来分别测试值是映射还是集合。

我不确定我对你在这里尝试做什么有足够的看法 - 我已经用宏代替了一个函数,因为我看不到样本中宏的必要性'给了。

;; Create a function to remove in a different way when given a map/set and a string
(defn remove- [v w]
  (dosync
     (cond 
        (map? @v)
        (ref-set v (dissoc @v (keyword w)))

        (set? @v)
        (ref-set v (disj @v w)))))

 ;; Set up some mutable refs
 (def m (ref {:a 1 :b 2}))
 (def s (ref #{"a" "b" "c"}))

 ;; Remove from the refs
 (remove- m "b") => {:a 1}
 (remove- s "b") => #{"a" "c"}

旁注 - 您确定是否需要使用refs?我知道来自C / Java背景,可变性是默认的,但到目前为止我还没有真正在Clojure中使用它。 Clojure非常强调不变性,大多数事情都可以通过在不可变值上使用函数来完成(通常非常优雅)。