Clojure

non-tail-position try block breaks mutable fields in deftype

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Declined
  • Affects Version/s: Release 1.3, Release 1.4
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

The :unsynchronized-mutable fields of a deftype cannot be set! inside a try block that is not in tail position of the method.

See file *demonstration.clj* for an complete code example.

Activity

Hide
Rich Hickey added a comment - - edited

I looked at this. The problem is that non-tail try blocks turn into closures, and thus the field gets propagated as a constant. IOW this can't work:

(deftype Foo4 [^:unsynchronized-mutable x]
  MutableX
  (set-x [this v]
    ((fn [] (set! x v)))
    v))

I'm not going to re-evaluate the try/closure approach right now, so I recommend you make a helper method that just does the assignment and then call that in the bigger context, as a workaround.

Show
Rich Hickey added a comment - - edited I looked at this. The problem is that non-tail try blocks turn into closures, and thus the field gets propagated as a constant. IOW this can't work:
(deftype Foo4 [^:unsynchronized-mutable x]
  MutableX
  (set-x [this v]
    ((fn [] (set! x v)))
    v))
I'm not going to re-evaluate the try/closure approach right now, so I recommend you make a helper method that just does the assignment and then call that in the bigger context, as a workaround.
Hide
Timothy Baldridge added a comment -

Closing this as it requires more than a simple bug fix. If you feel that Rich's work-around is unsatisfactory please create a clojure-dev discussion about rewriting try-catch.

Show
Timothy Baldridge added a comment - Closing this as it requires more than a simple bug fix. If you feel that Rich's work-around is unsatisfactory please create a clojure-dev discussion about rewriting try-catch.
Hide
Nicola Mometto added a comment -

The patch at ticket CLJ-1226 makes it possible to write

(deftype foo [^:unsynchronized-mutable x] MutableX (set-x [this v] (try (set! (.x this) v)) v))

that is probably a better workaround than writing a helper method

Show
Nicola Mometto added a comment - The patch at ticket CLJ-1226 makes it possible to write (deftype foo [^:unsynchronized-mutable x] MutableX (set-x [this v] (try (set! (.x this) v)) v)) that is probably a better workaround than writing a helper method

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: