This is a somewhat contrived example but there is a curious behavior that may or may not be a bug.
Suppose you have the following protocol:
(defprotocol P (f [this]))
And concrete type with a mutable parameter and lock:
(deftype T [^:volatile-mutable x lock]
P
(f [this]
(locking lock
(set! x true)
(prn ""))))
Compiler has no problem with this. But move the (prn "")
statement outside the (locking …)
block and you get:
(deftype T [^:volatile-mutable x lock]
P
(f [this]
(locking lock
(set! x true))
(prn "")))
Syntax error (IllegalArgumentException) compiling fn* at (REPL:4:5).
Cannot assign to non-mutable: x
David Miller spotted this behavior in the lastest ClojureCLR (see https://clojure.atlassian.net/browse/CLJCLR-122) and is sleuthing it on his end but the fact the same error is raised in JVM Clojure suggests that either there is a bug in Clojure proper, or some highly counterintuitive rule is at work here, the details of which are probably worth understanding. Why the compiler would view x as non-mutable here is not clear.