`extend-type string` doesnt work without wrapping the string object into `(str)`
Description
Environment
Activity
Mike Fikes April 10, 2016 at 6:24 AM
As Francis alludes to, this is not a bug. If you do (doc extend-type)
, it indicates the type-sym
can be string
to cover the base type js/String
, and it elaborates with
and if a user does try to use js/String
as the type-sym
argument, a diagnostic is issued:
Francis Avila April 8, 2016 at 12:41 AM
BTW this appears to be different from Clojure where primitives and boxed-primitives appear equal:
Not sure if clojurescript should try to replicate this more closely or not.
Clojurescript bottoms out with triple-equals in most cases, which is why primitives and boxes do not compare equal. To get them to compare equal would require adding special (instance? js/BOXED x) checks and some modifications to existing -equiv implementations which extend primitive types. (e.g. (extend-type number IEquiv ...) uses identical? without checking if the right-hand side is boxed or not.)
Francis Avila April 8, 2016 at 12:27 AM
This is because of boxing and the implementation of cljs.core._EQ_
By extending type js/String (the String object/class in javascript) instead of "string", your "this" will be the boxed string rather than the primitive string (in non-strict js mode--in strict mode it will be the primitive also). The (str this) is coercing the boxed string back to a primitive string.
The core issue is really:
You should really use
(ns my.car)
(defprotocol Car
(drive [this]))
(extend-type js/String
Car
(drive [this] (map #({"a" "A"} %) [this (str this)])))
(drive "a"); (nil "A") expected ("A" "A")
See the reproduction of the bug in a live environment with KLISPE here: http://app.klipse.tech/?sourcce=jira&cljs_in=(ns%20my.car)%0A%0A(defprotocol%20Car%0A%20%20(drive%20%5Bthis%5D))%0A%0A(extend-type%20js%2FString%0A%20%20Car%0A%20%20(drive%20%5Bthis%5D%20(map%20%23(%7B%22a%22%20%22A%22%7D%20%25)%20%5Bthis%20(str%20this)%5D)))%0A%0A%0A(drive%20%22a%22)%0A