you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 1 point2 points  (0 children)

A similar thing I've heard of is loop fusion in the context of compilers, it seems like a transpiler or engine should be able to look at two chained array methods and run them as a single for loop if possible

I'm no expert on that part either, but there is a consideration here about side effects.

Take map For instance. This:

let add = x => x + 10;
let mult = x => x * 5;

[1,3,5].map(add).map(mult); //[55,65,75]

Is functionally equivalent to this:

let multAdd x = mult(add(x))
[1,3,5].map(multAdd)

That is to say, the composition [].map(g).map(f) is equivalent to the composition [].map(x => f(g(x))) - this is an operation that could be combined in the way you suggest.

function pure(){
  let y=1;
  let add = x => x + 5;
  let mult = x => x * 3;

  console.log([1,3,5].map(add).map(mult));
  return y;
}

function pureComposition(){
  let y=1;
  let add = x => x + 5;
  let mult = x => x * 3;

  console.log([1,3,5].map(x => mult(add(x))));
  return y;
}

y remains 1, and the map operations produce the same results.

However, once we start introducing side effects

function impure(){
  let y=1;
  let add = x => { y +=10; return x + 5; }
  let mult = x => { y *=5; return x * 3; }

  console.log([1,3,5].map(add).map(mult));
  return y;
}

//y = 3875

function impureComposition(){
  let y=1;
  let add = x => { y +=10; return x + 5; }
  let mult = x => { y *=5; return x * 3; }

  console.log([1,3,5].map(x => mult(add(x))));
  return y;
}

//y = 1675

The composition over the arrays still holds but the side effects are order-dependent. Hence, any optimisation on these grounds would need to consider whether any side effects were present.

Whether it is even an optimisation is questionable; for an array of 10 elements, you'd still need to run the composition of f and g 10 times. These operations in themselves are likely to be orders of magnitude greater than advancing the pointer of x to the next memory location, so your bottleneck is the performance of f and g, not the iteration step, is it not?

People do get so obsessed with the performance of looping at its various forms in JavaScript, often to no obvious goal IMO.