Skip to content

Conversation

jfmengels
Copy link
Contributor

@jfmengels jfmengels commented Dec 12, 2021

This PR is based off of #63 (and until it gets merged, contains those same commits).

This transformer turns function composition into an anonymous function with a named parameter.

-- Elm
f1 >> f2
-- Without eol2
A2($elm$core$Basics$composeR, f1, f2);
-- With this transformation
var fn = function (_param_1) { return f2(f1(_param_1)); };

It makes #65 redundant because this transformation leads that function to have the exact same code as the transformation in that PR. I think that PR does help see the performance increases this can give.

Asset-size wise: I measured it on a single small application, and the size of the compiled JS code is reduced compare to without the transformation. But the gain gets reduced after minification and is reduced to 0 after gzip. But at least it didn't get worse!

There were a lot of cases where I try to make sure the performance doesn't get worse than what we currently have because of how the components get called, but in some cases I made it even faster.

I hopefully wrote a clear documentation of the transformation in the code, but I think the tests go a bit further detail, so do check out both.

Further work

There are still some improvements that can be done but I'll get to that later. For instance improving the following:

-- Given f1 = F2(...) 

-- Elm
f1 x >> f2
-- Without eol2
A2($elm$core$Basics$composeR, f1(x), f2);
-- With this transformation
var _decl_1 = f1(x),
        fn = function (_param_1) { return f2(_decl_1(_param_1)); };
-- Ideally
var fn = function (_param_1) { return f2(A2(f1, x, _param_1)); };

I already do this when encountering A3 expressions, so it's do-able, but a bit more work. The current solution is already an improvement in all cases (because it's pretty conservative) but we could go a step further when we know better.

Another one would be to change not calls into !, which would remove the cost of a function call. That said, I tried benchmarking the same idea for field accesses, and that didn't improve anything, so maybe this would not change much either.


I am welcome to suggestions and improvements (including but not limited to the name of the transform 😁 )

Also, please let me know how I can properly benchmark the results of this transformation and what the next steps should be before we merge it in.

PedroHLC pushed a commit to PedroHLC/elm-gobrrrrr that referenced this pull request Jan 21, 2022
mdgriffith#73

Copy other transformer

Get rid of unnecessary things

Apply replacement for composeL

Extract variable

Start count from 0

Inverse operations for composeL

Split tests

Fix replacement

Enable transformation

Add comments

Add test

Recurse through children first

Extract information

Give less confusing names

Move comment

Compose multiple functions

Remove dollar signs f

Add passing test

Add TODOs

Give unique names to introduced params to avoid conflicts

Add failing test

Add blocks

Wrap test code in IIFE

Insert new variable

Create insertion mechanism

Extract function calls to variables

Fix original source code

Remove TODO

Add explanation

Add test

Change test title

Support extracting variable from the first argument

Fix examples

Simplify test

Add failing test

Extract function

Remove unnecessary imports

Also extract when it's a function expression

Extract variable

Don't replace the functions that we just introduced

Change name of param

Change name of declarations

Formatting

Remove TODO

Add failing test

Make inserted variables start with a _

Call mergeFunctionCalls

Merge functions

Insert new declarations in the right block

Add TODOs

Move the declaration next to the function that uses it

Declare statements next to the return statement when possible

Make test code more real

Add test

Make condition more solid

Extract function to top-level

Rename tests

Create unique names manually

Support extracting function calls on property accesses

Remove ideas that don't seem to improve performance

Add failing tests

Move condition

Support A3 calls

Change conditions

Change conditions

Add TODO

Add failing test

Update test

Inline call to createCompositionCall in createLambda

Don't extract to variables for A3

Support wrapping in A2

Use AX functions for the second function as well

Add failing test

Extract to function

Re-use function

Move TODOs

Reverse conditions

Add invocationRegex

Increment the AX wrapper count

Add test for second function

Update source explanation

Don't increment AX calls when it already has the perfect number

Remove composeL and composeR definitions

Extract regexes to util module

Improve documentation

Don't replace calls to functions that only have a single argument

Add passing test

Make test clearer

Documentation improvements

Remove unnecessary import

Use mutable clone to update body
@jfmengels jfmengels force-pushed the lambdaify-function-composition branch from b3e4b7e to 20c3382 Compare February 6, 2022 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant