@igneo676 https://clojureverse.org/t/generating-es-modules-browser-deno/6116
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
in Clojure this works due to protocols being mapped to Java interfaces
k that makes sense. Thanks for the info!
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:
<http://demo.app|demo.app>> (-> js/document (.getElementById "63R"))
#object[HTMLSelectElement [object HTMLSelectElement]]
I tried instance?
, but that doesn’t distinguish ClojureScript objects:
<http://demo.app|demo.app>> (instance? js/Object. (-> js/document (.getElementById "1120R")))
true
<http://demo.app|demo.app>> (instance? js/Object. {})
true
I tried object?
, but that doesn’t work:
<http://demo.app|demo.app>> (object? (-> js/document (.getElementById "1120R")))
false
there's a low level thing cljs$lang$type
boolean field
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?
<http://demo.app|demo.app>> (.-cljs$lang$type js/Object.)
nil
<http://demo.app|demo.app>> (.-cljs$lang$type {})
nil
cljs.user=> (defrecord Foo [])
cljs.user/Foo
cljs.user=> (.-cljs$lang$type Foo)
true