我正在尝试使用Clojure 1.2,特别是deftype根据clojure.org文档支持的可变字段.
但是我不能让这套装置工作.更新字段的语法是什么?或者是否实现了可变性?
(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
Run Code Online (Sandbox Code Playgroud)
使用几天前的1.2快照.
Mic*_*zyk 43
deftype默认仍然是字段是不可变的; 要覆盖它,您需要使用适当的元数据注释要变为可变的字段的名称.此外,set!实例字段的语法也不同.进行上述工作的示例实现:
(deftype Point [^{:volatile-mutable true} x]
IPoint
(getX [_] x)
(setX [this v] (set! x v)))
Run Code Online (Sandbox Code Playgroud)
还有:unsynchronized-mutable.不同之处在于名称会向有经验的Java开发人员建议.;-)请注意,提供任一注释都会使该字段成为私有的附加效果,因此不再可能进行直接字段访问:
(.getX (Point. 10)) ; still works
(.x (Point. 10)) ; with annotations -- IllegalArgumentException, works without
Run Code Online (Sandbox Code Playgroud)
此外,1.2可能会支持语法^:volatile-mutable x作为简写^{:volatile-mutable true} x(这已经在一些新的数字分支上可用).
两个选项都在提到(doc deftype); 相关部分如下 - 记住警告!
可以使用元数据来限定字段:volatile-mutable true或:unsynchronized-mutable true,此时(方法体)将支持(set!afield aval).请注意,可变字段非常难以正确使用,并且只是为了便于在Clojure本身中构建更高级别的构造,例如Clojure的引用类型.它们仅供专家使用 - 如果:volatile-mutable或:unynchronized-mutable的语义和含义对您来说不是很明显,那么您就不应该使用它们.