This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-09-29
Channels
- # announcements (6)
- # babashka (23)
- # beginners (15)
- # biff (15)
- # calva (17)
- # clara (5)
- # clj-kondo (41)
- # cljdoc (2)
- # cljs-dev (67)
- # cljsrn (18)
- # clojure (19)
- # clojure-europe (25)
- # clojure-nl (2)
- # clojure-norway (9)
- # clojure-uk (2)
- # clojurescript (26)
- # core-typed (6)
- # cursive (15)
- # data-science (30)
- # datahike (1)
- # datomic (18)
- # docker (6)
- # emacs (10)
- # events (2)
- # graalvm (15)
- # graphql (5)
- # hugsql (4)
- # jobs-discuss (1)
- # joker (7)
- # lsp (36)
- # malli (28)
- # off-topic (46)
- # other-languages (1)
- # pathom (5)
- # pedestal (6)
- # polylith (5)
- # reitit (2)
- # releases (1)
- # rewrite-clj (63)
- # shadow-cljs (7)
- # spacemacs (16)
- # squint (6)
- # tools-deps (6)
- # xtdb (13)
@shaunlebron the reader macro metadata isn't evaluated:
> Note that metadata reader macros are applied at read-time, not at evaluation-time
from the end of https://clojure.org/reference/metadata
If you want it to be evaluated use e.g. with-meta
or vary-meta
yeah, the ^js/React.Element
there becomes the :tag
meta of the (provider)
list. which the compiler will then apply as the :tag
in the AST and used for analysis (eg. inference) purposes
Hmm, so how does ^js []
not work if ^js ()
does? (Neither work in clojure btw.)
clojure will always resolve tags during compilation, since it wants to map for actual JVM things (eg. classes). CLJS almost never resolves tags at all, not even sure if ever.
yeah but I thought it dropped tag info just like it drops all other reader metadata (line, col, etc)
ClojureScript 1.11.60
cljs.user=> (meta ^js [])
WARNING: Use of undeclared Var cljs.user/js
{:tag nil}
cljs.user=> (meta ^js ())
{:tag js}
@U060FKQPN: i think the rule is that cljs evals metadata on all expressions except lists
right i think it blocks metadata eval on lists for invoke exprs, and happens to catch the empty list case
nah, way earlier than that. https://github.com/clojure/clojurescript/blob/9562ae11422243e0648a12c39e7c990ef3f94260/src/main/clojure/cljs/analyzer.cljc#L4311
From that code, it seems as if the tag should've been replaced with cljs.core/IList
. Why is it still js
then?
I'm guessing the infer-type analyzer pass just overrides it again. since that just looks at the unevaluated form
Does this work for documentation? > Values provided inside metadata reader macros in ClojureScript are only evaluated when they precede evaluated collection literals— except lists.
I'll give you one more:
cljs.user=> (let [a 1] (meta ^a ()))
{:tag a}
cljs.user=> (let [a 1] (meta ^a '()))
nil
:D
(probably because '()
is actually (quote ())
which is not ()
by itself)I think the description still works for that then! right?
^a
was attached to the quote form unevaluated, then quote evaluated to ()
with no metadata
err, quote wasn’t evaluated, I mean compiled probably
I modified the description to account for this:
(defn foo ^a [] 1)
[]
is a collection literal but is unevaluated
Honestly, I have no idea how to describe all this without it becoming even more confusing to a reader.
I agree, but I only went down here because I saw ^js
and realized my ^meta
docs were wrong about evaluating symbols
I won’t put it front and center summary, but it should be a footnote in the details
I think the relevant bit is whether the "thing" ends up as a runtime thing, or is just "syntax" (ie. for macros)
yeah I like that
so in defn
the ^a []
never ends up anywhere in the code. it is just used by the analyzer to define the return type
it still is just a vector with :tag a
meta, but since it never ends up in the runtime its never evaluated and thus not resolved
okay, so anytime metadata reader macros are used on values available to the runtime, it’s evaluated.
and maybe not mention the empty list exception
is this still related to the ^js
docs? I don't think this is relevant to any of that at all. there are really only a couple places ^js
should be used. maybe should just add the 3 examples for that or so? 😛
I realized last month that my ^meta
doc was wrong though: https://github.com/cljs/api/issues/187
I said something like ^foo
=> ^{:tag <value at foo>}
, so that’s what I’m trying to clear up there
> I think the relevant bit is whether the "thing" ends up as a runtime thing, or is just "syntax" (ie. for macros)
So anytime ^a foo
can be emitted as (with-meta foo {:tag a})
, you can know a
is evaluated?
well thats a bad example since foo
is a symbol and never actually ends up in the code 😛
Feels like all these metadata threads are a perfect source of materials for some Clojure quiz. :D
@U05224H0W dang you’re right, just when I think I understand something:
cljs.user=> (let [a 1 foo []] (with-meta foo {:tag a}))
^{:tag 1} []
cljs.user=> (let [a 1 foo []] ^a foo)
[]
I don’t think there’s a clear rule then, not one I can write at least
well the rule is that the metadata is always applied to what is read, so symbols, lists, etc
right, so the rule for the context would be too complicated?
well if you want to explain macros? 😛 can't really come up with a way to explain it simply
I never use it for runtime stuff, so I consider it a syntax only thing for the compiler
Is there a way to show code emitted from the repl?
oh nice, :repl-verbose
you can use something like this https://code.thheller.com/shadow-grove-playground/0.4.0/
Strange, the verbose option for repl doesn’t seem to work for me:
$ clj -M -m cljs.main --repl-opts "{:repl-verbose true}" --repl
docs say it should print the compiled JS: https://clojurescript.org/reference/repl-options#repl-verbose
thanks, that works!
ClojureScript 1.11.60
cljs.user=> (set! *print-fn-bodies* true)
true
cljs.user=> (fn [] (let [a 1] ^a []))
#object[ret__7815__auto__ "function (){
var a = (1);
return cljs.core.with_meta(cljs.core.PersistentVector.EMPTY,new cljs.core.PersistentArrayMap(null, 1, [new cljs.core.Keyword(null,"tag","tag",-1290361223),a], null));
}"]
I added the simplest possible note as I could on this stuff here: http://cljs.github.io/api/syntax/meta