我正在尝试使用Clojure 1.2,特别是deftype
根据clojure.org documentation支持的可变字段。
但我无法让套装发挥作用。更新字段的语法是什么?或者是否实现了可变性?
(definterface IPoint
(getX [])
(setX [v]))
(deftype Point [x]
IPoint
(getX [this] x)
(setX [this v] (set! (.x this) v)))
user=> (def p (Point. 10))
user=> (.getX p)
10
user=> (.setX p 20)
ClassCastException: user.Point cannot be cast to compile__stub.user.Point
使用几天前的1.2快照。
答案 0 :(得分:43)
deftype
的默认值仍然是字段是不可变的;要覆盖它,您需要使用适当的元数据注释要变为可变的字段的名称。此外,set!
实例字段的语法也不同。实现上述工作的示例实现:
(deftype Point [^{:volatile-mutable true} x]
IPoint
(getX [_] x)
(setX [this v] (set! x v)))
还有:unsynchronized-mutable
。不同之处在于名称会向有经验的Java开发人员建议。 ;-)请注意,提供任何一个注释都会使该字段成为私有的附加效果,因此不再可能直接访问字段:
(.getX (Point. 10)) ; still works
(.x (Point. 10)) ; with annotations -- IllegalArgumentException, works without
此外,1.2可能支持语法^:volatile-mutable x
作为^{:volatile-mutable true} x
的简写(这已经在一些新的数字分支上提供)。
(doc deftype)
中提到了这两个选项;相关部分如下 - 请注意警告!
可以限定字段 元数据:volatile-mutable true或:unsynchronized-mutable 是的,在这个方法中将支持(set!afield aval) 身体。请注意,可变字段非常难以使用 正确地,并且仅用于促进更高层的建设 Clojure中的级别构造,例如Clojure的引用类型 本身。它们仅供专家使用 - 如果语义和 含义:volatile-mutable或:unynchronized-mutable不是 对你来说很明显,你不应该使用它们。
答案 1 :(得分:0)