Fork me on GitHub

I recall maybe a couple of reports but that’s because people wanted it to be treated specially


but I more or less rejected that


since we coerce to nil I don’t think anybody notices


I ran into that sort of question when thinking about the construct

(when-not (nil? x) x)
which yields a value identical to nil when x is js/undefined. (I had hit this in the first change here and ended up concluding that perhaps that construct was in use prior to js/undefined and nil being equivalent.) The only other place where I've seen this concept is that js/undefined appears for unbound vars.


Of perhaps historical interest, p. 32 of ClojureScript: Up and Running has > What is logical true? In ClojureScript, nil, false, and the undefined value (written js/undefined) are logical false, and anything else is logical true. While this seems to imply 3 false values, perhaps this is older than the stance of treating JavaScript null and js/undefined as equivalent to ClojureScript nil. On p. 42 it has a bit more > ClojureScript's nil is identical to null in JavaScript; it is used where a value is logically absent, empty, or meaningless. To use it as a literal, just use the special symbol nil. ClojureScript does not use JavaScript's undefined value, but you can refer to it as js/undefined. Again, while arguably "accurate," this text seems to either predate the unification of null and undefined, or it chose to gloss over it (or was simply unaware).


TL;DR, though, I've also never seen any need to care about js/undefined


yeah can’t remember who decided to treat undefined as nil, it might have been before myself, whatever the case it was definitely done in the first year


Up & Running came out pretty early and was probably already falling behind 😛


and looks like undefined is logically false since commit 0

Roman Liutikov09:07:55

Is this difference between cljs and clj expected?

;; clj
(defprotocol HTML
  (to-html [this]))

(extend-protocol HTML
  (to-html [this] "html"))

(to-html (range 10)) ;; this works
;; cljs
(defprotocol HTML
  (to-html [this]))

(extend-protocol HTML
  (to-html [this] "html"))

(to-html (range 10)) ;; this doesn't work
;; No protocol method defined for type cljs.core/Range
;; but `(implements? ISeq (range 10)) ;; true`

Roman Liutikov09:07:46

If yes, then how the same can be achieved in ClojureScript?


The same sort of issue arises with defmulti /`defmethod`: While hierarchies based on keywords are honored, if you use type there is no type hierarchy in the ClojureScript side to make use of. Perhaps this all should be documented on


If you look at the implementation of isa? in ClojureScript, you can see that the type inheritance aspect is commented out. I wonder, is the "JavaScript type inheritance relationship" mentioned in the isa? docstring just a result of replacing "Java" with "JavaScript" when doing the port? (Or is there perhaps an intent to try to support something here in the future?)


@roman01la not supported - you can simulate it with extend-type default and handling it there

Roman Liutikov14:07:38

@dnolen thanks! could there be a warning or something that tells it’s not supported?


we might revisit it later - but not a priority and not interested in a warning about it


what makes this harder to implement in JS?


that "cljs differences" page says boxed booleans are irrelevant to if. But there's still the same behaviour in CLJS as CLJ (I think?).

cljs.user=> (if (js/Boolean. false) 1 2)
cljs.user=> (if (.valueOf (js/Boolean. false)) 1 2)


huh, also this evaluates to 2 in CLJ

cljs.user=> (if (boolean (js/Boolean. false)) 1 2)


just a curiosity obviously 😛


@ambrosebs re: extending a protocol - no interfaces that’s the only reason it works in Clojure


you can also run into problems via AOT if I recall


extending the protocol is not safe - interface works


@ambrosebs constructing Boolean String Number etc. is a disaster on JVM & JS


should be avoided


I'm learning about how JS's new works. Am I right in saying these are the common kinds of values used as ctors in CLJS? 1. JS built-ins 2. deftype's 3. something annotated as @constructor in GClosure


In particular, you normally wouldn't write a defn that's actually a ctor, right?


@ambrosebs you kinda have to use defn with manually annotated @constructor in cases where you need inheritance. eg. extends React.Component


since that is not supported by deftype it gets done via defn manually


I see, thanks! is this pattern ever used by normal users?


I think every react wrapper has some hack like this. in typical user code I'd guess its much rarer


although I have done it once or twice so it does happen