Immutable.js - 懒惰序列

tld*_*ldr 7 javascript facebook lazy-evaluation lazy-sequences

我最近听说过Facebook的Immutable.js库(https://github.com/facebook/immutable-js).我对他们的文档中的以下内容感到困惑:

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
Run Code Online (Sandbox Code Playgroud)

过滤器如何只调用两次,映射一次?

dse*_*ara 13

由于关于序列的惰性评估的映射和过滤器的逻辑

地图

在映射序列上调用的last()返回mapper函数处理的原始序列的last().

例如:

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

将输出64并且将调用map 一次,因为它唯一的做法是获取原始序列的最后一个元素(8)并将其映射到x => x*x(得到64)

过滤

last()调用过滤后的序列,将反向遍历序列,直到找到符合条件的sequnce值.所以,例如

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

WIll输出7并且调用过滤器两次,因为它首先调用过滤器(x => x%2)为8,它返回0表示javascript为false(因此应该过滤),然后再次调用过滤器函数得到7%2 = 1对于javascript是真的并且返回该值作为最后一个没有调用过滤器functoin了.

作为帮助理解的其他示例:

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

将调用过滤器函数四次,一次调用8次(结果为假),一次调用6次(假再次调用),一次调用4次(假再次调用),最后调用3次调整(最终结果为真)

将两个部分放在一起

你的例子:

var oddSquares = Immutable.Sequence(1,2,3,4,5,6,7,8)
   .filter(x => x % 2).map(x => x * x);
console.log(oddSquares.last());
Run Code Online (Sandbox Code Playgroud)
  1. 要获取映射序列的last()值,它首先获取已过滤序列的last()值
  2. 要获取已过滤序列的last()值,它首先获取原始序列(8)的last()值并再次对过滤函数(x => x%2)进行评估,并在第一时间调用它
  3. 由于8%2 = 0,它在JS上是假的并且应该被过滤,因此,我们移动到下一个值(7)并使用此值再次调用过滤器函数
  4. 7%2 = 1,它在JS上是正确的,不应该被过滤,因此,这是过滤序列的最后一个值
  5. 我们有映射序列所需的最后一个值(7),所以我们只调用mapper函数(x => x*x)一次得到49,最后的结果

最后,我们称为过滤器函数两次,映射器函数只调用一次