or just don't use tagged literals in code and you don't have to worry about it 😉
In either case, still unclear how to do that in a cljc-friendly way.
it works basically the same as in clojure and you need to be kinda careful what you return in the reader when used in code. when used in the regular EDN reader or so it doesn't matter much since you just get whatever you returned. when used in code the compiler needs to be able to emit code that is somehow able to reconstruct the returned object. in clojure thats done via print-dup
I believe and in CLJS you implement the multi-method you linked.
thus ... don't use it in code since thats not always practical. just calling (whatever/foo 1 2 3)
is pretty much always better than #whatever/foo [1 2 3]
. certainly less headaches 😛
IIRC there is some special support for records but thats about it
On the finer points of tag-handlers and time https://clojure.atlassian.net/browse/CLJS-3272?jql=project%20%3D%20CLJS
and the fact that they're read with java and used in js.
@dominicm An example of a working CLJC-based tagged-literal project that spans Clojure and both JVM and self-hosted ClojureScript is https://github.com/mfikes/precise
@mfikes that has the same problem I am trying to overcome on the JVM:
user=> (read-string "#exact/ratio \"2/3\"")
(com.gfredericks.exact// (com.gfredericks.exact/string->integer "2") (com.gfredericks.exact/string->integer "3"))
It returns code instead of objects. Compare with, e.g. uuid:
user=> (read-string "#uuid \"bdd2c05b-91a3-4e67-83ca-dcbd76ebe44c\"")
#uuid "bdd2c05b-91a3-4e67-83ca-dcbd76ebe44c"
It seems to me that libraries need to return code for clojurescript, and objects for clj, but they have no way to distinguish.
Oh, that's interesting. I wasn't aware that read-string
behaved that way.
I bet you need to bind *data-readers*
when using read-string
, but it has been a while since I've been down in that code
read-string uses default-data-readers too
Yeah, there is something subtle that is making inst and uuid behave differently, it seems. Hrm.
@mfikes that would be https://github.com/clojure/clojurescript/blob/b68f0a0de19384f736ab10912001519249737e56/src/main/clojure/cljs/compiler.cljc#L423-L425
hmm why do I get a 404 on that link?
the issue is simply that the exact/ratio
returns a code form which when encountered by the compiler will simply compile as regular code
I am too
might be a bug if clojure doesn't do that. read-string
however doesn't eval
so totally normal to get the returned "code" as data
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/compiler.cljc#L424
doing it in code does require implementing the multimethod
I'm pretty sure that you're not intended to return a code form from data readers.
Not clear from the docs
yes. the question is whether clojure does indead handle it as basically a quoted list or also compiles it happily
clojure expects a tagged reader function to return an object
how so?
it seems totally acceptable to me to return a quoted form from a tagged reader
if embedded in code it will be evaluated normally
just like syntax-quote returns code
to me returning an object vs code seem to be both valid, different, usages of tagged reader and i can't see why one would be expected over the other
similar to how both (defmacro x [] (Object.))
and
(defmacro y [] `(Object.))
are okthe difference to me seems in what the usage of a tagged literal is supposed to be, if to be embedded in code, returning code is ok since it will be evaluated, if just for reading then obviously not
yeah
I think the issue of whether you expect it to be eval'ed is important
the thing in cljs vs clj is that in clj objects are self-evaluating, in cljs only if the compiler knows how to
if you're just calling read-string or something, then that's just read
but even in clj, it will only self-evaluate when running through the repl, if you try to embed them and AOT it may explode if there's no print-dup
Unfortunately, that emit-constant* is not part of the public compiler API. There's no way in user space to define reader literals which work with read-string
and also in clojurescript.
Well technically cljs is just a Clojure library, so everything is possible :)
God, I love this language.