Immutable.js - 懒惰序列

时间:2014-09-16 17:18:28

标签: 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

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

1 个答案:

答案 0 :(得分:13)

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

<强>地图

在映射序列上调用的

last()返回映射器函数处理的原始序列的last()。

例如:

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

输出64并将仅调用地图 ,因为它唯一能做的就是获取原始序列的最后一个元素(8)并将其映射到x =&gt; 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());

WIll输出7并将调用过滤器仅两次,因为它首先调用过滤器(x =&gt; 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());

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

将两个部分放在一起

你的例子:

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. 要获取映射序列的last()值,首先获取已过滤序列的last()值
  2. 要获取已过滤序列的last()值,它首先获取原始序列(8)的last()值并再次对过滤函数(x =&gt; x%2)进行评估,调用它第一次
  3. 由于8%2 = 0,因此在JS上是假的并且应该被过滤,因此,我们移动到下一个值(7)并且再次使用此值调用过滤器函数
  4. 7%2 = 1,在JS上是正确的,不应过滤,因此,这是过滤后序列的最后一个值
  5. 我们有映射序列所需的最后一个值(7),所以我们称映射函数(x =&gt; x * x)只有一次得到49,最终结果
  6. 最后,我们称为过滤函数两次,映射器函数仅一次