Изменяемые поля в Clojure deftype? - PullRequest
21 голосов
/ 28 июня 2010

Я пробую Clojure 1.2, а именно изменяемые поля, которые поддерживаются в deftype согласно документации clojure.org .

Но я не могу заставить работать телевизор.Каков синтаксис для обновления поля?Или еще не реализована изменчивость?

(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 несколько дней назад.

Ответы [ 2 ]

43 голосов
/ 28 июня 2010
По умолчанию

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 x в качестве сокращения для ^{:volatile-mutable true} x (это уже доступно в некоторых новых числовых ветвях).

Оба варианта упомянуты в (doc deftype); соответствующая часть следует - учтите предостережение!

Поля могут быть квалифицированы с метаданными: volatile-mutable true или: unsynchronized-mutable true, в какой момент (set! afield aval) будет поддерживаться в методе тела. Обратите внимание, что изменяемые поля чрезвычайно сложно использовать правильно, и присутствуют только для облегчения строительства высшего конструкции уровня, такие как ссылочные типы Clojure, в Clojure сам. Они только для экспертов - если семантика и последствия: volatile-mutable или: unsynchronized-mutable не являются Сразу видно, вы не должны их использовать.

0 голосов
/ 28 марта 2019

Как и большинство вещей в Clojure, поля типов, определенных с помощью deftype, являются неизменяемыми.В то время как вы можете обойти это, используя аннотации :volatile-mutable / :unsynchronized-mutable, это вообще не распространено.С одной стороны, такие аннотации сделают поле частным, поэтому только методы, определенные для типа, смогут получить к нему доступ (и, следовательно, установить его).Но что еще более важно, такие конструкции подвержены гонкам данных.

Когда требуется изменчивость, idomatic Clojure будет использовать один из ссылочных типов Clojure, например atom или ref.

...