人, 先看一下代码:
(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
....))
有人有什么建议吗?非常感谢。
答案 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非常强调不变性,大多数事情都可以通过在不可变值上使用函数来完成(通常非常优雅)。