2010-06-28 6 views
19

Estoy probando Clojure 1.2, específicamente campos mutables compatibles con deftype de acuerdo con clojure.org documentation.Campos mutables en Clojure deftype?

Pero no consigo que el equipo funcione. ¿Cuál es la sintaxis para actualizar un campo? ¿O no se ha implementado 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 

Usando una instantánea de 1.2 desde hace unos días.

Respuesta

40

deftype Por defecto, los campos son 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 como los nombres sugerirían a un desarrollador experimentado de Java. ;-) Tenga en cuenta que ya sea proporcionando anotación tiene el efecto adicional de hacer el campo privado, por lo que el acceso directo de campo ya no es posible:

(.getX (Point. 10)) ; still works 
(.x (Point. 10)) ; with annotations -- IllegalArgumentException, works without 

Además, es probable que 1,2 apoyar la sintaxis ^:volatile-mutable x como forma abreviada de ^{: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 - ¡tenga en cuenta la advertencia!

campos que puede ser calificado con los metadatos: volátil-mutable verdadero o: no sincronizado-mutable cierto, en cuyo punto (conjunto lejos aval!) Será apoyado en el método cuerpos. 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 más altas, como los tipos de referencia de Clojure, en Clojure . Solo son para expertos: si la semántica y las implicaciones de de: volátil-mutable o: mutable no sincronizado no son evidentes para usted, no debería utilizarlas.

+2

Gracias. Eres una mina de oro de información, me alegro de tenerte aquí :) –

+0

Que bueno que lo digas, gracias. :-) –

+0

Quiero enfatizar ... otra vez ... "no deberías estar usándolos". No usar: volátil-mutable y no sincronizado-mutable. A menos que ya sepa que esta advertencia no se aplica a usted y entienda por qué estoy diciendo la advertencia nuevamente ;-) – Jason

Cuestiones relacionadas