This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-07
Channels
- # babashka (20)
- # beginners (72)
- # biff (7)
- # calva (15)
- # clj-kondo (36)
- # clj-on-windows (5)
- # cljs-dev (30)
- # clojure (27)
- # clojure-europe (2)
- # clojure-nl (1)
- # clojure-norway (6)
- # clojure-uk (2)
- # clojurescript (26)
- # conjure (14)
- # cursive (17)
- # events (1)
- # honeysql (5)
- # hyperfiddle (1)
- # leiningen (1)
- # off-topic (3)
- # reitit (5)
- # shadow-cljs (1)
- # xtdb (13)
Function calls like this:
(defn foo [x y] (+ x 1))
(foo 1 2)
are compiled to:
cljs.user.foo = (function cljs$user$foo(x,y){
return (x + (1));
});
cljs.user.foo.call(null,(1),(2));
Are there any performance disadvantages to .call
instead of compiling to a direct call?I guess it's hard to tell in general as this relies on the behavior of the JS runtime
with :static-fns true
it'll skip the .call
(true by default for :advanced
, always true for shadow-cljs outside the REPL)
Nice. Btw, I just noticed that Closure optimizes this:
function hello(name) {
alert('Hello, ' + name);
}
hello.call(null, 'New user');
to:
alert("Hello, New user");
lol@U04V15CAJ There is some higher-order stuff along these lines as well. For example see https://blog.fikesfarm.com/posts/2017-11-16-direct-higher-order-function-calls.html
@U04VDQDDY Really interesting. What is the default of fn-invoke-direct
in 2022?
haven't verified in a long time but I believe this is still an issue here https://github.com/thheller/shadow-cljs/blob/49fb078b834e64f63122e3a8ad3ddcd1f4485969/src/main/shadow/build/api.clj#L67-L70
Just sharing this as info here, in case anyone has thoughts on this.
https://github.com/thheller/shadow-cljs/commit/e8e0cf9973bafcd472ffa1066bbd8ae8c83e5cab
@thheller has done some work on emitting ES6 modules via Closure, but unfortunately, binding
in cljs.core
generates a re-assignment of an import
which isn't valid in ES6.
Perhaps there's a way around it.
It would perhaps be a too big of a change to CLJS to model dynamic vars as mutable objects?
@thheller Another thought: along with a dynamic var foo
one could emit set_foo
and emit (set_foo x)
instead of foo = x
or so?
the problem is more general than that. any set!
on a "var" can cause this, so its not limited to binding
.
foo.bar.x = 1
gets renamed to var aA = 1;
and all cross-chunk references are then export { aA }
and import { aA } ...
on the others. can't aA = 2
in the others since that is not allowed in ESM
I think its just not worth using the chunk output type in closure for now. its relatively new so who knows what other issues it may have
var
would also probably break given that it also generates a potentially cross-chunk assignment
only reason the renamed-prefix-namespace
"trick" (via $APP
) is not ideal is because it probably hinders tree-shaking in esbuild and others
otherwise its probably better than what the closure stuff does, as that generates quite a few exports which is not ideal if you want other places to consume those modules
thanks for testing my attempts 😉 in the end the output is still a bit better than before, so at least got something out of it.
> adding the setter would allow it technically but we can't do that for every var why not actually? I think only top-level vars would be sufficient
well given what :advanced
does it just inline any function like that. so foo.bar.set_x = function(v) { foo.bar.x = v; }
is just turned into foo.bar.x = v
as one of the first steps of the optimizations