2010-06-28 3 views
19

나는 clojure.org documentation에 따라 deftype에서 지원되는 Clojure 1.2, 특히 변경할 수있는 필드를 시험 중이다.Clojure deftype의 가변 필드?

그러나 나는 세트를 작동시킬 수 없습니다. 필드를 업데이트하는 구문은 무엇입니까? 아니면 아직 구현되지 않은 가변성인가?

(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 

며칠 전부터 1.2 스냅 샷을 사용합니다.

답변

40

deftype의 기본값은 여전히 ​​필드를 변경할 수 없습니다. 이것을 무시하려면 적절한 메타 데이터로 변경할 수있는 필드의 이름에 주석을 달아야합니다. 또한 인스턴스 필드의 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 true} x 속기로이 구문 ^:volatile-mutable x을 지원합니다 일부 새로운 수치 분기에서 이미 사용 가능합니다.)

두 옵션 모두 (doc deftype)에 언급되어 있습니다. 관련 부분은 다음과 같습니다 - 훈계를 염두에 두십시오! 메타 데이터와

필드가 규정 될 수 : 방법 기관에서 지원되는 지점 (멀리 군함을 설정!)에, 비 동기화 - 변경 가능한 사실 : 사실 휘발성 가변 나. 변경 가능한 필드는 을 올바르게 사용하기가 극히 어렵고 Clojure 자체에서 Clojure의 참조 유형과 같은 상위 구성 요소 인 레벨 작성을 용이하게하기 위해서만 제공됩니다. 그것들은 전문가 용입니다. - 의미와 의 의미가 : volatile-mutable 또는 : unsynchronized-mutable이 즉시 명백하지 않다면, 당신은 그것을 사용해서는 안됩니다.

+2

감사합니다. 당신은 정보의 금광이야, 여기있어 기뻐 :) –

+0

네, 정말 고마워. :-) –

+0

나는 다시 강조하고 싶다 ... "당신은 그들을 사용해서는 안된다". volatile-mutable 및 : unsynchronized-mutable을 사용하지 마십시오. 이미이 경고가 귀하에게 적용되지 않으며 경고를 다시 말하고있는 이유를 이해하지 못한다면 ;-) – Jason