Campos mutables en Clojure Deftype?
(1)
deftype
predeterminada de deftype
es que los campos sean inmutables; para anular esto, debe anotar los nombres de los campos que deben ser mutables con los metadatos apropiados. Además, la sintaxis para set!
De los campos de instancia es diferente. Una implementación de ejemplo para hacer el trabajo anterior:
(deftype Point [^{:volatile-mutable true} x]
IPoint
(getX [_] x)
(setX [this v] (set! x v)))
También hay :unsynchronized-mutable
. La diferencia es que los nombres sugerirían a un desarrollador Java experimentado. ;-) Tenga en cuenta que proporcionar una anotación tiene el efecto adicional de hacer que el campo sea privado, por lo que ya no es posible el acceso directo al campo:
(.getX (Point. 10)) ; still works
(.x (Point. 10)) ; with annotations -- IllegalArgumentException, works without
Además, es probable que 1.2 admita la sintaxis ^:volatile-mutable x
como abreviatura para ^{:volatile-mutable true} x
(esto ya está disponible en algunas de las nuevas ramas numéricas).
Ambas opciones se mencionan en (doc deftype)
; La parte relevante sigue: ¡Cuidado con la admonición!
Los campos se pueden calificar con los metadatos: volatile-mutable true o: unsynchronized-mutable true, en cuyo punto (set! Afield aval) se admitirán en los cuerpos de los métodos. Tenga en cuenta que los campos mutables son extremadamente difíciles de usar correctamente y están presentes solo para facilitar la construcción de construcciones de nivel superior, como los tipos de referencia de Clojure, en Clojure. Solo son para expertos, si las semánticas y las implicaciones de: volatile-mutable o: unsynchronized-mutable no son evidentes para usted, no debe usarlas.
Estoy probando Clojure 1.2, específicamente los campos mutables que se admiten en deftype
acuerdo con la documentación de clojure.org .
Pero no consigo que el set funcione. ¿Cuál es la sintaxis para actualizar un campo? ¿O no se ha implementado todavía la mutabilidad?
(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
Utilizando una instantánea 1.2 desde hace unos días.