This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # 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)))
(f true). I partially expected that type hints would only propagate to places where it is statically known to be valid, and that
loopisn’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
loop seem to differ in this regard.
^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”.
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
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
@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
From what little experience I have with this particular case, the warning appeared to be relatively easy to implement, while deoptimizing, on the surface, might be more difficult.