clojure-dev

Issues: https://clojure.atlassian.net/browse/CLJ | Guide: https://insideclojure.org/2015/05/01/contributing-clojure/
plexus 2019-10-31T13:54:28.183400Z

(defprotocol IFoo
  (dest [this]))

(deftype Foo [^:volatile-mutable dst]
  IFoo
  (dest [this]
    (locking this
      (set! dst 123))))
;; Works ok

(deftype Foo [^:volatile-mutable dst]
  IFoo
  (dest [this]
    (let [dest (locking this
                 (set! dst 123))]
      dest)))
;; Unhandled clojure.lang.Compiler$CompilerException
;; Caused by java.lang.IllegalArgumentException
;; Cannot assign to non-mutable: dst
would this be a Clojure bug?

alexmiller 2019-10-31T13:59:06.184Z

I'd guess it's probably due to not allowing closing over mutables (https://clojure.atlassian.net/browse/CLJ-274)

alexmiller 2019-10-31T14:04:31.184600Z

or do you need the syntax (set! (.dst this) 123) for this?

alexmiller 2019-10-31T14:05:15.186Z

user=> (doc set!)
-------------------------
set!
  (set! var-symbol expr)
  (set! (. instance-expr instanceFieldName-symbol) expr)
  (set! (. Classname-symbol staticFieldName-symbol) expr)
Special Form
  Used to set thread-local-bound vars, Java object instance
fields, and Java class static fields.

  Please see <http://clojure.org/vars#set>
  Used to set thread-local-bound vars, Java object instance
fields, and Java class static fields.

alexmiller 2019-10-31T14:05:49.187200Z

From the link, "When the first operand is a symbol, it must resolve to a global var."

dominicm 2019-10-31T14:06:53.188500Z

The advantage of clojure test for all the things is: - outputs (editor integration, tap, junit, cli exit code) - selection (metadata) - tooling (parallels, pretty diffs) These are (mostly, excepting perhaps editor integration) generic to generative, unit and integration tests I think? I think that's what you're getting at, but I'm not sure. It's worth making sure we all know what we're talking about.

plexus 2019-10-31T14:09:19.188800Z

(.dst this) seems to work, thanks @alexmiller!

dominicm 2019-10-31T14:43:41.189400Z

For other curious people, this is the generative test runner used by clojure https://github.com/clojure/test.generative/blob/master/src/main/clojure/clojure/test/generative/runner.clj

dominicm 2019-10-31T14:47:27.190Z

I'd summarize it by saying it's using different keys on vars to locate tests to clojure.test, and uses those as different inputs.

2019-10-31T16:06:09.191800Z

So is it just an accident of implementation that it happens to work sometimes with the (set! symbol expr) variant, i.e. when used inside of a deftype to mutate fields of the type instances?

2019-10-31T16:06:54.192300Z

Because as far as I can tell it does work in core.rrb-vector across dozens if not hundreds of uses.

ghadi 2019-10-31T16:13:43.193300Z

It’s the fact that it is wrapped in locking, which has an internal try block

ghadi 2019-10-31T16:14:09.193700Z

If that is the Q

alexmiller 2019-10-31T16:15:53.194Z

why does (set! (.dst this) 123) work then?

alexmiller 2019-10-31T16:17:04.194500Z

I assume it's some difference in compilation but I didn't look any more closely at it

alexmiller 2019-10-31T16:17:28.194900Z

I guess it doesn't have to close over the mutable in that case, just invokes via interop?

👍 1
ghadi 2019-10-31T16:20:59.195400Z

Yeah I guess so? Seems accidental

alexmiller 2019-10-31T16:26:19.195800Z

I mean, this is exactly the sort of place where you should be able to do this kind of thing

bronsa 2019-10-31T23:50:50.198100Z

only locals are closed over, the let + locking combination causes the try to be lifted into a fn while just locking doesn't cause let puts the try block in a different compilation context

bronsa 2019-10-31T23:53:06.201200Z

not trivial to fix cause changing the compilation of mutable locals (e.g. transforming foo to (.foo this)) is a potentially breaking change when closing over is done intentionally (capturing value vs capturing reference)

bronsa 2019-10-31T23:57:20.202300Z

the hoisting patch that compiles hoisted functions as methods would fix that

❤️ 1
2019-10-31T23:57:38.202900Z

The auto hoisting is the source of a number of oddities

bronsa 2019-10-31T23:59:11.205100Z

afaict that hoisting is a workaround for a compiled bug wrt locals (not sure if a bug or intentional compilation choice), but alternatives are possibile - - t.e.jvm iirc doesn't need that