This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-07
Channels
- # babashka (20)
- # beginners (72)
- # biff (7)
- # calva (15)
- # clj-kondo (36)
- # clj-on-windows (5)
- # cljs-dev (30)
- # clojure (27)
- # clojure-europe (2)
- # clojure-nl (1)
- # clojure-norway (6)
- # clojure-uk (2)
- # clojurescript (26)
- # conjure (14)
- # cursive (17)
- # events (1)
- # honeysql (5)
- # hyperfiddle (1)
- # leiningen (1)
- # off-topic (3)
- # reitit (5)
- # shadow-cljs (1)
- # xtdb (13)
I'm writing some .cljc
code that does extend-protocol
. In Clojure, it extends String
and Object
and for ClojureScript I tried js/String
and js/Object
and while the code works, I get these warnings:
WARNING: Extending an existing JavaScript type - use a different symbol name instead of js/String e.g string at line 267 /home/seanc/oss/honeysql/src/honey/sql.cljc
WARNING: Extending an existing JavaScript type - use a different symbol name instead of js/Object e.g object at line 267 /home/seanc/oss/honeysql/src/honey/sql.cljc
However, if I "use a different symbol name" the extensions don't work. What do this warning actually mean and what should I use in extend-protocol
rather than js/String
and js/Object
?Regarding the meaning: https://clojure.atlassian.net/browse/CLJS-528
Also, I just tried the suggested string
and object
with a Node-backed CLJS REPL and it seems to be working just fine.
Hmm, doesn't work at all with cljs-test-runner
which is what HoneySQL uses.
So I'm guessing this is a ClojureScript version issue?
It might be because Object
in CLJ is a catch-all and object
in CLJS is specifically for something that satisfies object?
.
cljs.user=> (extend-protocol P object (foo [_] (println "object P")))
#object[Function]
cljs.user=> (foo #js [])
Execution error (Error) at (<cljs repl>:1).
No protocol method P.foo defined for type array:
cljs.user=> (foo #js {})
object P
nil
I'm using cljs-test-runner
3.8.0 which is the latest version but it uses ClojureScript org.clojure/clojurescript {:mvn/version "1.10.773"}
Is there an equivalent "catch all" type for cljs to Object?
(and what about js/String
?)
A-ha, on CLJS the catch-all is default
.
And for js/String
it's just the suggested string
.
When I use string
instead of js/String
a lot of tests fail so that's clearly a bad substitution.
(unless you construct a js/String
object instead of using a string JS primitive - it's not an intuitive concept in JS at all)
This is the code in question https://github.com/seancorfield/honeysql/blob/develop/src/honey/sql.cljc#L267-L282
OK, default
works instead of js/Object
. Thanks.
Clone the repo and change that js/String
to string
and you'll see.
clojure -T:build ci
is how to run the tests.
Hmm, so I need both changes together. I'd tried just string
instead of js/String
while I still had Object
and it didn't work. OK. Thanks for checking @U2FRKM4TW I appreciate it.
And thanks for the explanation/pointers. I don't do cljs so I find these differences from clj to be annoying/bewildering at times -- and things seem to change very frequently in the cljs world without much external documentation.
That particular CLJS warning has been introduced 9 years ago, so it's definitely much older than the warnings from CLJ about all the new functions being shadowed by libraries because the names are so popular. ;) I don't feel like similar things happen noticeably more often than in CLJ, but of course YMMV.
Also, I had no clue about all this myself - just git blame
d the CLJS source code and found the issue with the explanation. And checked the source code for extend-type
to find what the catch-all word should be.
The reason you don't want to use extend-type and extend-protocol with built in "types” is because “extending” means mutating those objects, and it's generally frowned upon to mutate built in objects