This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-06-09
Channels
- # announcements (16)
- # babashka (28)
- # beginners (27)
- # calva (39)
- # chlorine-clover (6)
- # cider (8)
- # clara (28)
- # cljs-dev (19)
- # cljsrn (22)
- # clojure (78)
- # clojure-australia (3)
- # clojure-europe (64)
- # clojure-nl (3)
- # clojure-norway (14)
- # clojure-spec (2)
- # clojure-uk (11)
- # clojurescript (11)
- # core-async (24)
- # datomic (3)
- # deps-new (5)
- # emacs (9)
- # fulcro (4)
- # gis (2)
- # graalvm (9)
- # honeysql (2)
- # hoplon (5)
- # instaparse (1)
- # introduce-yourself (5)
- # jobs (5)
- # luminus (4)
- # observability (7)
- # off-topic (6)
- # pathom (18)
- # pedestal (5)
- # polylith (4)
- # re-frame (2)
- # reagent (1)
- # reitit (1)
- # remote-jobs (7)
- # shadow-cljs (47)
- # specter (1)
- # sql (27)
- # testing (6)
- # tools-deps (4)
- # vim (3)
- # xtdb (8)
I was looking into porting over https://github.com/stuartsierra/clojure.walk2 to clojurescript. My initial tests show a 2-5x speedup. But I am having some issues dispatching records correctly. There are certainly some clojure/script nuances around protocols that I am not up to speed on. So here is a little clojure to clojurescript comparison getting at the crux of the matter: (this example code is just mimicking a portion of the walk2 code. Clojure
(defprotocol SomeP
(report [coll]))
(extend-protocol SomeP
java.lang.Object
(report [x]
(println :SomeP :path :object :is-record? (record? x)))
clojure.lang.IRecord
(report [x]
(println :SomeP :path :record)))
(extend-type clojure.lang.PersistentArrayMap
SomeP
(report [x]
(println :SomeP :path :map)))
(defrecord Foo [a b c])
(report 1234)
;; :SomeP :path :object :is-record? false
(report {:a 1})
;; :SomeP :path :map
(report (map->Foo {:a 1 :b 2 :c 3 :extra 4}))
;; :SomeP :path :record
Clojurescript
(defprotocol SomeP
(report [coll]))
(extend-protocol SomeP
object
(report [x]
(println :SomeP :path :object :is-record? (record? x)))
number
(report [x]
(println :SomeP :path :number))
cljs.core.IRecord
(report [x]
(println :SomeP :path :record)))
(extend-type cljs.core.PersistentArrayMap
SomeP
(report [x]
(println :SomeP :path :map)))
(defrecord Foo [a b c])
(report 1234)
;; :SomeP :path :number
(report {:a 1})
;; :SomeP :path :map
(report (map->Foo {:a 1 :b 2 :c 3 :extra 4}))
;; :SomeP :path :object :is-record? true
Without the extend on object
then (report (map->Foo {...}))
fails so the extend on cljs.core.IRecord
does nothing.
So my question is in clojurescript can I use extend-protocol
to work on any record type?
I can always just check with record?
when the record gets dispatched as an object but I was hoping to avoid that.@slack1003 it cannot be avoided - you cannot extend a protocol w/ a protocol which is what you're trying to do
Is it possible to test for whether an object is a JavaScript object or a ClojureScript object? I would like to test when something is going to print as an #object
at the REPL, for example:
> (-> js/document (.getElementById "63R"))
#object[HTMLSelectElement [object HTMLSelectElement]]
I tried instance?
, but that doesn’t distinguish ClojureScript objects:
> (instance? js/Object. (-> js/document (.getElementById "1120R")))
true
> (instance? js/Object. {})
true
I tried object?
, but that doesn’t work:
> (object? (-> js/document (.getElementById "1120R")))
false
technically you can also extend the printer protocols on JS types, so even though it may not be a CLJS type that doesn't mean it'll guaranteed print as #object
Forgive my ignorance, but how do I check for the field?
> (.-cljs$lang$type js/Object.)
nil
> (.-cljs$lang$type {})
nil