This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-31
Channels
- # announcements (20)
- # asami (14)
- # aws (6)
- # babashka (15)
- # beginners (83)
- # biff (6)
- # calva (93)
- # cider (3)
- # clj-kondo (21)
- # cljdoc (106)
- # cljs-dev (32)
- # clojure (165)
- # clojure-dev (78)
- # clojure-europe (54)
- # clojure-italy (9)
- # clojure-nl (9)
- # clojure-norway (24)
- # clojure-uk (4)
- # clojurescript (6)
- # community-development (2)
- # conjure (2)
- # core-typed (14)
- # datahike (4)
- # datomic (2)
- # emacs (40)
- # events (1)
- # fulcro (11)
- # graalvm-mobile (29)
- # graphql (8)
- # honeysql (19)
- # java (1)
- # jobs (1)
- # lsp (232)
- # malli (5)
- # membrane (112)
- # nextjournal (11)
- # off-topic (63)
- # portal (12)
- # re-frame (6)
- # reagent (3)
- # reitit (4)
- # rewrite-clj (2)
- # shadow-cljs (25)
- # tools-deps (6)
we have implemented for penpot, high performance uuidv4 and pseudo uuidv1 here: https://github.com/penpot/penpot/blob/develop/common/src/app/common/uuid_impl.js#L97, if it can work as inspiration, (it is implemented in JS for the same reason, performance)
Any reason defn
type hints aren't accepted on arg vecs like suggest by the CLJ docs?
https://clojure.org/reference/java_interop#typehints
More context: https://clojurians.slack.com/archives/C06E3HYPR/p1648720725216029
@borkdude just an artifact of history, but type hints also serve a a slightly different purpose in ClojureScript
we should accept them on the vector - mostly for portability since I don't think it serves much of a purpose
I noticed for keywords, the emitted javascript can have long strings that are repeated. For example:
(def b :my.extremely.long.out.of.control.keyword/thing)
=>
cljs.user.b = new cljs.core.Keyword("my.extremely.long.out.of.control.keyword","thing","my.extremely.long.out.of.control.keyword/thing",(3471023));
Closure advanced doesn't do anything about that either besides renaming the constructor. Would it make sense to move to a constructor that only needs 1-2 strings instead of 3?in shadow-cljs you can set :compiler-options {:shadow-keywords true}
which optimizes this specific thing
got somewhat less useful when closure removed aliasable strings but can still be beneficial
Very interesting, testing that now. Regarding aliasable strings, I see this is their reasoning: https://github.com/google/closure-compiler/wiki/FAQ#closure-compiler-inlined-all-my-strings-which-made-my-code-size-bigger-why-did-it-do-that
so shadow$keyword("foo", "bar")
became shadow$keyword(a, "bar")
which can substantially reduce code size if you have a lot of namespaced keywords
My fat bundle went from 3200 KB (uncompressed) to 2959 KB with the shadow-maps on, seems worth it to leave on for me. (I probably still need to do something about the size)
you are trading a very very tiny bit of performance for this but in my tests that never was noticable. the default keyword construction precomputes the hash, the :shadow-keywords
delay that until the keyword is first hashed
should be better percentage wise since the precomputed hash numbers don't compress well
I want to try a trick to compress even further - just reusing keyword instances. I'm testing this with esprima now, to just process the bundle after advanced minification. The nasty part is having to find what the keyword constructor got renamed to.
what do you mean reusing keyword instances? they are only constructed once in release builds
shadow-cljs generates a .shadow-cljs/builds/<your-build-id>/release/closure.variable.map
file. just a text file that contains the names of renamed properties. eg.
shadow$keyword:K
shadow$keyword_fqn:N
(those are the functions used by :shadow-keywords
, not using the constructor anymore
@isak I don't think so, unless you have some kind evidence that such a thing would have a significant benefit
nothing stops anyone from using the constructor so changes here are also bring on other undesirable issues
Right now, when you call a function passed as callback or stored as field on deftype, the compiler generates the following code:
// with :fn-invoke-direct true
(self__.selector.cljs$core$IFn$_invoke$arity$1
? self__.selector.cljs$core$IFn$_invoke$arity$1(new_source_value)
: self__.selector(new_source_value))
Is there a way to avoid this check and do direct call to the self__.selector(new_source_value)
? I know that this callback is a
javascript function and it will never have the cljs$core$IFn$_invoke$arity$1