2010-06-28 8 views
19

Sto provando Clojure 1.2, campi specificamente mutabili supportati in deftype in base allo clojure.org documentation.Campi mutabili in ccljure deftype?

Ma non riesco a far funzionare il set. Qual è la sintassi per l'aggiornamento di un campo? O non è ancora implementata la mutevolezza?

(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 

Utilizzo di un'istantanea 1.2 da pochi giorni.

risposta

40

deftype L'impostazione predefinita è che i campi siano immutabili; per sovrascriverlo, è necessario annotare i nomi dei campi che devono essere sostituiti con i metadati appropriati. Inoltre, la sintassi per set! dei campi di istanza è diversa. Un esempio di implementazione per rendere il lavoro di cui sopra:

(deftype Point [^{:volatile-mutable true} x] 
    IPoint 
    (getX [_] x) 
    (setX [this v] (set! x v))) 

C'è anche :unsynchronized-mutable. La differenza è che i nomi suggerirebbero a uno sviluppatore Java esperto. ;-) Si noti che la fornitura sia di annotazione ha l'ulteriore effetto di rendere il campo privato, in modo che l'accesso campo diretto non è più possibile:

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

Inoltre, 1.2 sarà probabilmente sostenere la sintassi ^:volatile-mutable x come abbreviazione di ^{:volatile-mutable true} x (questo è già disponibile su alcuni dei nuovi rami numerici).

Entrambe le opzioni sono menzionate in (doc deftype); Segue la parte rilevante: attenzione all'ammonizione!

campi può essere qualificato con i metadati: volatili mutevole vero o: unsynchronized-mutabile vero, a questo punto (set lontano Aval!) Sarà sostenuta nel metodo corpi. Si noti bene che i campi mutabili sono estremamente difficili da usare correttamente e sono presenti solo per facilitare la creazione di più elevati costrutti di livello , come i tipi di riferimento di Clojure, in Clojure stesso. Sono solo per esperti - se la semantica e le implicazioni di: volatile-mutable o: unsynchronized-mutable non sono immediatamente apparenti, non dovresti usarli.

+2

Grazie. Sei una miniera d'oro di informazioni, felice di averti qui :) –

+0

Piacere a dirlo, grazie. :-) –

+0

Voglio sottolineare ... di nuovo ... "non dovresti usarli". Non utilizzare: volatile-mutable e: non sincronizzato-mutabile. A meno che tu non sappia già che questo avviso non si applica a te e capisci perché sto affermando di nuovo l'avviso ;-) – Jason