This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-02-06
Channels
- # aatree (1)
- # alda (9)
- # beginners (63)
- # boot (124)
- # braid-chat (8)
- # cider (44)
- # cljs-dev (44)
- # clojure (79)
- # clojure-dev (1)
- # clojure-russia (47)
- # clojurescript (105)
- # community-development (16)
- # cursive (3)
- # datavis (1)
- # datomic (54)
- # editors (10)
- # editors-rus (10)
- # emacs (18)
- # garden (1)
- # hoplon (5)
- # jobs (1)
- # ldnclj (6)
- # lein-figwheel (2)
- # luminus (1)
- # off-topic (29)
- # om (49)
- # overtone (5)
- # parinfer (12)
- # proton (2)
- # re-frame (5)
- # reagent (6)
- # ring-swagger (1)
- # slack-help (3)
- # spacemacs (1)
- # yada (42)
I had asked in the main channel about
(defn f [^boolean b]
(loop [x b]
(if x
(recur 0)
:done)))
returning for (f true)
.
I partially expected that type hints would only propagate to places where it is statically known to be valid, and that loop
isn’t one (as opposed to let
).
At this point, either the code above is “incorrect, malformed”, or there is something in my understanding that is off, or there is a compiler bug (or any of the three.)I suppose, at least in the example above, if that were a let
then you could, via static analysis, conclude that x
holds a Boolean value, whereas with loop
you can’t do that owing to the fact that recur
can result in x
containing a different type of value (number in, the example).
My thinking is roughly: To determine the static type of a bound local, you’d have to analyze all the places where it can be set. And let
vs. loop
seem to differ in this regard.
Exactly, ^boolean
propagates to x
, and that is the core of my question: Whether this propagation is overly aggressive (unsafe), without further analysis.
The alternative is “that’s just the way type propagation works, and the program I wrote in the example is simply malformed or incorrect”.
It is a static thing, affecting the emitted JavaScript in a static fashion. (See http://blog.fikesfarm.com/posts/2015-12-04-boolean-type-hints-in-clojurescript.html)
Conceptually it doesn't feel right because of the dynamic nature of the implied binding in the loop, but ultimately the resulting js code is all that matters here.
So, don't use loop/reccur because I don't like them - use for, into, or anything else. 😉
@bronsa: That’s what I suspected. Perhaps ClojureScript could do the same kind of analysis.
@mfikes: ah I see the conversation got moved here - yeah confirming that the types match would be right thing to do
Perhaps related http://dev.clojure.org/jira/browse/CLJS-375
But, I see what you are saying @dnolen : Type hint propagation is going to occur here, regardless of what is in recur
forms, so the code is invalid, and you are suggesting that a WARN is in order.
Captured the above with an enhancement ticket: http://dev.clojure.org/jira/browse/CLJS-1561
Attached a patch that results in
cljs.user=> (defn f [^boolean b]
#_=> (loop [x b]
#_=> (if x
#_=> (recur 0)
#_=> :done)))
WARNING: recur target parameter x has inferred type boolean, but being passed type number at line 4
@mfikes: is compilation affected or is just a warning emmitted? in CLJ mismatched recur types actually affect compilation
I guess what I'm asking is, will the CLJS compiler deoptimize that case or emit a warning and compile to unsafe code that will break on (recur 0)
?
@mfikes @dnolen just FYI, in case aligning with clj (deoptimizing rather than just emitting a warning), becomes an option the CLJ compiler does this by recursively re-macroexpanding/analyzing the macro bodies until no mismatched recur locals are present