0

各位,先看代码:

(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”,但显然 case 不能在宏定义中使用,因为“未评估测试常量。它们必须是编译时文字”,以下代码将不起作用:

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

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

4

1 回答 1

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"}

附带说明-您确定需要使用参考吗?我知道来自 C/Java 背景,可变性是默认设置,但到目前为止,我实际上从未在 Clojure 中使用过它。Clojure 非常强调不可变性,并且大多数事情都可以通过对不可变值使用函数来完成(通常非常优雅)。

于 2013-08-13T10:13:18.767 回答