Share your thoughts in the 2024 State of Clojure Survey!

Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by

Closing over mutable fields should be forbidden completely (and generate compiler exception), not just when trying to set! them. As the change of the mutable field does not propagate into closed over ones, this leads to surprising bugs:

`
(defprotocol P
(-set [this])
(-get [this])
(-get-fn [this]))

(deftype T [^:unsynchronized-mutable val]
P
(-set [this] (set! val :bar))
(-get [this] val)
(-get-fn [this] (fn [] val)))

(def x (->T :foo))

(def xf (-get-fn x))

user> (-set x)
:bar
user> (-get x)
:bar
user> (xf)
:foo ;; should be :bar !!!
`

4 Answers

0 votes
by

Comment made by: wagjo

related issue CLJ-274

0 votes
by

Comment made by: gshayban

In the given example, the close-over happens before the set!, so the closure gets the value, not an assignable container. This is consistent with the rest of the language (pass-by-value not by mutable container)

0 votes
by

Comment made by: wagjo

Thanks for explanation. The ticket is about a proposal that closing over a mutable field should result in error being thrown, an not in a value. If value is desired, an explicit let binding will have to be used. So far, I haven't found a valid use case where closing over mutable field and getting the value closed over is the intended and wanted behavior.

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-1560 (reported by wagjo)
...