Ответ 1
deftype
default по-прежнему должен иметь неизменяемые поля; чтобы переопределить это, вам необходимо аннотировать имена полей, которые должны быть изменены с помощью соответствующих метаданных. Кроме того, синтаксис для 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 true, в какой момент (set! aal aval) будет поддерживаться методом тела. Хорошо заметьте, что изменяемые поля чрезвычайно сложны в использовании правильно, и присутствуют только для содействия созданию более высоких как, например, Clojure ссылочные типы, в Clojure сам. Они предназначены только для экспертов - если семантика и последствия: volatile-mutable или: unsynchronized-mutable не являются вам сразу же не следует использовать их.