7

I recently heard about Facebook's Immutable.js library (https://github.com/facebook/immutable-js). I am confused about the following from their documentation:

var oddSquares = Immutable.Sequence(1,2,3,4,5,6,7,8)
  .filter(x => x % 2).map(x => x * x);
console.log(oddSquares.last());

In this example, no intermediate arrays are ever created, filter is only called twice, and map is only called once

How is filter called only twice, map once?

1 Answer 1

14

Because of the logic of map and filter regarding lazy evaluation of sequences

map

last() called over a mapped sequence return the last() of the original sequence processed by the mapper function.

So for example:

 var mappedSequence = Immutable.Sequence(1,2,3,4,5,6,7,8).map(x => x * x);
 console.log(mappedSequence.last());

Will output 64 and will call map only once, because the only thing it does is get the last element of original sequence (8) and map it on x => x * x (resulting on 64)

filter

last() called over a filtered sequence, will reverse walk the sequence until it finds a value on sequnce matching the criteria. So, for example

 var mappedSequence = Immutable.Sequence(1,2,3,4,5,6,7,8).filter(x => x % 2);
 console.log(mappedSequence.last());

WIll output 7 and will call filter only twice, because it call the filter (x => x % 2) for 8 first, it returns 0 meaning false for javascript (so it should be filtered), and then call the filter function again to get 7 % 2 = 1 being true for javascript and returning that value as the last without calling filter functoin anymore.

As additional example to help understand:

 var mappedSequence = Immutable.Sequence(1,2,3,4,6,8).filter(x => x % 2);
 console.log(mappedSequence.last());

Would call the filter function four times, one for 8 (resulting false), one for 6 (false again), one for 4 (false again), and finally for 3 (finally resulting true)

Putting both pieces together

Your example:

var oddSquares = Immutable.Sequence(1,2,3,4,5,6,7,8)
   .filter(x => x % 2).map(x => x * x);
console.log(oddSquares.last());
  1. To get the last() value of mapped sequence, it first get the last() value of filtered sequence
  2. To get the last() value of filtered sequence, it first get the last() value of original sequence (8) and evaluate it agains the filter function ( x => x % 2 ), calling it for first time
  3. Since 8 % 2 = 0, it is false on JS and should be filtered, so, we move to the next value (7) and call the filter function again with this value
  4. 7 % 2 = 1, it is true on JS and should NOT be filtered, so, this is the last value of the filtered sequence
  5. We have the last value (7) required by the mapped sequence, so we call mapper function (x => x * x) only one time to get 49, the final result

At the end, we get called the filter function two times and the mapper function only once

3
  • 1
    IMHO the wording in the documentation is subtly wrong. The functions you supply to the filter and map functions are only called twice and once, respectively. In this case lambdas but you can supply named functions as well.
    – wensveen
    Commented Sep 8, 2022 at 6:56
  • I am sure my english was pretty broken then and even now :( (a bit less broken), I am sure I made lot of mistakes. I will appreciate a well written answer. I don't have time to review this , sorry (I am just sure I made some gramatical/vocabulary mistake, that's for sure)
    – dseminara
    Commented Sep 9, 2022 at 20:16
  • Your English is fine, I was talking about the documentation. And it's a bit of a nitpick. There's a distinction between the filter/map functions and the functions that you supply to these functions as the argument (callbacks). So when you say 'mapper function' it's clear that you don't talk about the map function, but when you say 'filter function' there's ambiguity between the function named filter and the function you supplied as the argument. seq.filter(ffn); // ffn = filtering function seq.map(mfn); // mfn = mapping function
    – wensveen
    Commented Sep 11, 2022 at 7:12

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.