cljs-dev

ClojureScript compiler & std lib dev, https://clojurescript.org/community/dev
plexus 2020-06-26T10:09:32.290700Z

➜ clj
user=> (type ^{:type ::foo} [])
:user/foo

➜ cljs
cljs.user=> (type ^{:type ::foo} [])
cljs.core/PersistentVector
Seems ClojureScript's type doesn't honor the :type metadata the way that Clojure does.

plexus 2020-06-26T10:13:30.291700Z

For comparison, Clojure

(defn class
  "Returns the Class of x"
  ^Class [^Object x] (if (nil? x) x (. x (getClass))))

(defn type 
  "Returns the :type metadata of x, or its Class if none"
  [x]
  (or (get (meta x) :type) (class x)))
ClojureScript
(defn type
  "Return x's constructor."
  [x]
  (when-not (nil? x)
    (.-constructor x)))
So Clojure type is really just class but also checks (:type (meta ...)). ClojureScript doesn't have class.

plexus 2020-06-26T10:15:25.293600Z

happy to make a ticket/patch, but would like confirmation that this is considered something that needs fixing. If so, should we do the same thing in cljs, i.e. rename type to class, and make type check for meta then delegate to class, or should cljs remain class-less, and we only add the metadata check to type

dnolen 2020-06-26T12:04:31.294200Z

this would be a breaking change - also hard to see the value of it

dnolen 2020-06-26T12:04:56.294700Z

originally Rich left out type, and I added it to be able to do some useful type based dispatch

dnolen 2020-06-26T12:07:21.295600Z

usually alignment is good but I'm concerned that this one might have some repercussions - it would be interesting to know what use cases you have in mind

dnolen 2020-06-26T12:07:43.296100Z

in Clojure I nearly always use type the same way I use it in ClojureScript - I don't need the class bit (or the metadata stuff)

dnolen 2020-06-26T12:12:48.296800Z

it's just to get host type distinction for dispatch

plexus 2020-06-26T12:36:03.298700Z

using :type metadata can be quite convenient, for instance for multimethod dispatch, consider Clojure's own print-method used by pr and friends

plexus 2020-06-26T12:36:07.298900Z

(defmulti print-method (fn [x writer]
                         (let [t (get (meta x) :type)]
                           (if (keyword? t) t (class x)))))

plexus 2020-06-26T12:37:13.300Z

which makes it easy to add specific dispatching for certain cases, for example Malli has a lot of reify calls, so they all end up with a different class, but they all have the same :type metadata https://github.com/metosin/malli/blob/master/src/malli/core.cljc#L95

dnolen 2020-06-26T12:38:14.300800Z

print-method is not a great example since we don't need that

plexus 2020-06-26T12:38:28.301400Z

clojure.pprint on the other hand does not look at the :type metadata, making it tricky to add dispatching for these types

dnolen 2020-06-26T12:38:36.301500Z

what I mean is what can you not do w/ what you currently have

dnolen 2020-06-26T12:38:47.301900Z

if you change type you change all uses of it

dnolen 2020-06-26T12:39:01.302400Z

so anything thing that was flowing through will break if it happens to have the metadata

dnolen 2020-06-26T12:39:33.303200Z

so the balance of "this is useful" / "this breaks stuff"

plexus 2020-06-26T12:39:38.303500Z

I can do everything fine, I can write my own type that looks at (meta (:type)), it's just an incosistency that seemed worth pointing out.

dnolen 2020-06-26T12:39:39.303600Z

is not very compelling

dnolen 2020-06-26T12:39:56.304100Z

I understand what you're saying - I'm justing saying type is everywhere

dnolen 2020-06-26T12:40:00.304300Z

and you're going to change it

plexus 2020-06-26T12:40:15.304700Z

yeah, fair enough, that does warrant careful consideration 🙂

plexus 2020-06-26T12:40:42.304900Z

I guess we're stuck with this one

dnolen 2020-06-26T12:52:38.306300Z

I think when we have a better testing story it will be easier to make these kinds of decisions - but right now it's hard to know what will happen

plexus 2020-06-26T13:33:28.307200Z

I've been keeping some notes for an eventual "differences between clojure and clojurescript to watch out for" blog post, so this can go right onto the list