Skip to content

Instantly share code, notes, and snippets.

@mfikes
Last active August 22, 2018 03:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mfikes/d0f88ae51f8ead862989a5be0caaf623 to your computer and use it in GitHub Desktop.
Save mfikes/d0f88ae51f8ead862989a5be0caaf623 to your computer and use it in GitHub Desktop.
Improved and / or inference

This compares the current ClojureScript compiler inference algorithm for and and or forms with a proposed new algorithm.

Note that if ClojureScript infers that an expression is of string type, the inference will be string. If it is string or number, this would be represented as the set #{string number}. If it is nil, this is represented as clj-nil, and inclusion of clj-nil in a set means the value can be nil. If it can be any type, then the inference is any.

The goal of the new inference algorithm is to identify a smaller set of types that are produced by a given and or or expression, while still being correct (by not excluding any type that could be produced.)

One reason for identifying the narrowest set of correct types is that, by constraining things, the compiler can, at times produce more efficient JavaScript. On the other hand, if things are unconstrained, then the compiler must be conservative and make no assumptions.

form old inference new inference
(and nil 10) #{number clj-nil} clj-nil
(and "a" nil 10) #{number string clj-nil} clj-nil
(and 10 "a") #{number string} string
(and (even? (int (system-time))) "a" 10) #{boolean number string} #{boolean number}
(and "a" (even? (int (system-time))) 10) #{boolean number string} #{boolean number}
(and (when (even? (int (system-time))) "a") 10) #{number string clj-nil} #{number clj-nil}
(let [x ^any []] (and x 10)) #{any number} #{boolean number clj-nil}
(let [x ^any []] (and :kw (if x "3" 10))) #{cljs.core/Keyword number string} #{number string}
(or nil 10) #{number clj-nil} number
(or "a" nil 10) #{number string clj-nil} string
(or 10 "a") #{number string} number
(or (even? (int (system-time))) "a" 10) #{boolean number string} #{boolean string}
(or "a" (even? (int (system-time))) 10) #{boolean number string} string
(or (when (even? (int (system-time))) "a") 10) #{number string clj-nil} #{number string}
(or (when (even? (int (system-time))) (even? (int (* 10 (system-time))))) 10)) #{boolean number clj-nil} #{boolean number}
(let [x ^any []] (or x 10)) #{any number} any
(let [x ^any []] (or (if x "3" 10) :kw)) #{cljs.core/Keyword number string} #{number string}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment