Fork me on GitHub
#cljs-dev
<
2018-01-08
>
rauh10:01:52

What's the reason an IIFE is created here:

(fn [a]
  (let [X (inc a)
        f #()]
    f))

rauh10:01:28

Is it for performance? Asking, because Closure doesn't inline/break-up the IIFE when they're deep inside a function.

rauh10:01:00

Just removing the IIFE in that case reduced my code size by 5% (both, gzipped & non-gzipped)

dnolen13:01:21

in single arity case IIFE’s can be removed

rauh13:01:15

@dnolen I mean why do any IIFE's at all in a let? We should only need them in a loop where we need to lock-in the mutable loop variables, right?

dnolen14:01:10

that’s not why you need them in general no

dnolen14:01:25

I agree we should not be introducing them unnecesssarily

dnolen14:01:47

I don’t really understand why you keep talking about let and far as I know what you’re describing shouldn’t be true - but you’ll have to point me to some code you think isn’t doing the expected thing

dnolen14:01:10

rewinding a bit - in JS many kinds of statements cannot syntactically be present in certain positions - so we must introduce IIFEs to get around that, as FEs are one of the few forms in JS that can appear nearly anywhere legally.

rauh14:01:53

Ok let's back up. Why does this code:

(fn []
  (let [a 1, b 2]
    #()))
Create an IIFE:
function (){
var a = (1);
var b = (2);
return ((function (a,b){
return (function (){
return cljs.core.List.EMPTY;
});
;})(a,b))
}

rauh14:01:23

The thing is: Because most real world code has some kind of bindings in the function we currently wrap all functions within a defn with an IIFE and passing all local bindings.

rauh14:01:30

I did a quick hack on the emitter and removed the local let bindings from the IIFE, the result is a --IMO pretty significant-- 5% reductions in code size. I'm going to guess that the performance would also actually improve (to be tested).

rauh15:01:12

To answer myself: B/c otherwise this would regress: https://dev.clojure.org/jira/browse/CLJS-154

rauh15:01:21

FWIW, emitting a const js syntax for lets would fix this and shift the burden to Google closure compiler to do the right thing.

dnolen15:01:01

yeah that codegen example would have made it clearer 🙂

dnolen15:01:37

that’s not compiler IIFE in general, that an IIFE which explicitly captures local vars for the loop problem.

dnolen15:01:32

re: const won’t Closure do something similar to prevent reassignment? Need to know what Google Closure will generate before bothering.

rauh15:01:42

@dnolen Closure is currently buggy. Does some very very strange stuff: http://bit.ly/2CUs2IE (link to closure compiler on app spot)

rauh15:01:08

I'm filing a bug with them. Edit:

rauh16:01:29

@dnolen Re "how does Closure compile const captures": It looks like it passes in a JS object with the local bindings and resets this JS object on every loop. Then creates an IIFE with a single variable (the JS object).

dnolen16:01:23

huh, I don’t know - needs a lot of research then

dnolen16:01:28

this doesn’t seem that important to me

rauh18:01:02

Shadowing doesn't actually work properly with dashes in the first segment of the ns. For instances, my entire project is under srs-c.* and I do:

(let [srs-c "works", srs_c "boom"] 
  (anything-calling-somethign-from-srs-c-fails))

rauh18:01:19

Is this a known issue or new one?

rauh18:01:04

I certainly don't want to make the compiler 2x slower with this. Looking through git history a bit earlier and there used to be a ns-first-segments, that was a set of the first segments of all namespaces. Maybe this should be re-introduced and maintained as namespaces are parsed?

dnolen20:01:00

@rauh file a minor issue and the context there, thanks

andyparsons20:01:01

Hi cljs team. We (http://workframe.com) are working 100% in cljs on the frontend, looking at 2018 as a time to contribute in whatever way benefits the most developers. Planning to send out out a survey to Clojure NYC (which we run) and other meetup lists to gain and share knowledge about the ecosystem and js dependencies in particular. We’d love your input on the content if you have any https://docs.google.com/forms/d/e/1FAIpQLSeheqZbpIpMQycTllcOkdJuX6_8C6tr0_I0zunCTb-g2F5zzA/viewform

juhoteperi20:01:05

I tested my Closure update patch with new 20180101 release and it is broken again (or probably I did something wrong when I tested master two weeks ago). I'll try bisecting Closure-compiler changes to see what breaks this.

juhoteperi22:01:03

I think I got the processing working again. Had to change to passes being called during module processing.

juhoteperi22:01:21

Looks like compiler now needs a change to call all functions from processed modules using ["default"] property

dnolen22:01:00

@andyparsons seems like useful information

andyparsons22:01:26

@dnolen great, I’ll share results with everyone

dnolen22:01:54

@juhoteperi even if exported?

dnolen22:01:16

I’m assuming that’s not true

juhoteperi22:01:47

for example CJS create-react-class or left-pad which only export single function module.exports = function() { ... } are now turned into module$path$left_pad$index = {}; module$path$left_pad$index["default"] = function() { ... };

juhoteperi22:01:23

And in React's case the object is exported under default

juhoteperi22:01:46

I think all CJS modules use default to match ES6 modules

anmonteiro22:01:06

@juhoteperi or is it because we’re processing every module as :es6?

dnolen22:01:00

yes that little trick is probably a problem now

juhoteperi22:01:44

Closure ES6 passes only touch scripts which use ES6 module features

juhoteperi22:01:51

Skipping ES6 passes and only using CJS results in the same output for CJS modules

juhoteperi23:01:57

Yes, though it will be really confusing to implement this now that we need to use default property even for CJS modules

thheller23:01:24

@juhoteperi not that confusing, but maybe breaking change. whenever you used :as thing and directly accessed that (thing) you now you :default thing instead which is consistent with ES6

thheller23:01:51

can also change (thing) to automatically use default

thheller23:01:33

maybe even warn when using :as and directly referencing it