迭代器上的Scala贴图不会产生副作用

pla*_*pus 6 iterator scala map

为什么会这样,

scala> List(1,2,3,4).iterator.map((x: Int) => println(x))
Run Code Online (Sandbox Code Playgroud)

不打印出来

1
2
3
4
Run Code Online (Sandbox Code Playgroud)

List(1,2,3,4).map((x: Int) => println(x))
List(1,2,3,4).foreach((x: Int) => println(x))
List(1,2,3,4).iterator.foreach((x: Int) => println(x))
Run Code Online (Sandbox Code Playgroud)

都这样做?

换句话说,为什么迭代器上的地图将类型T映射到单位并且副作用无法显示这些副作用?

编辑:

另外,为什么如果迭代器是惰性的,下面的lazyMap调用实际上会从头到尾计算新的迭代器(提供完整的新迭代器)?

def lazyMap[T, U](coll: Iterable[T], f: T => U) = new Iterable[U] {
  def iterator = coll.iterator map f
}

scala> lazyMap(List(1,2,3,4), (x: Int) => x + 1)
res4: java.lang.Object with Iterable[Int] = (2, 3, 4, 5)
Run Code Online (Sandbox Code Playgroud)

om-*_*nom 7

迭代器上的原因映射是懒惰的,你需要一些严格性:

scala> List(1,2,3,4).iterator.map((x: Int) => println(x))
res0: Iterator[Unit] = non-empty iterator

// nothing actually happened yet, just remember to do this printing things

scala> res0.toList
1
2
3
4
res1: List[Unit] = List((), (), (), ())
Run Code Online (Sandbox Code Playgroud)

当你在迭代器上做foreach时很明显你正在做副作用,所以懒惰将是不受欢迎的.关于地图,我不会这么说.

UPD

至于你的编辑:这种行为的原因是,对于语句结果存在toString的隐式调用,而这反过来又会严格破坏迭代器 - 试试你自己的代码:

scala> { lazyMap(List(1,2,3,4), {(x: Int) => println(x); x + 1}); 1 }
Run Code Online (Sandbox Code Playgroud)

你会看到f永远不会调用该函数


dhg*_*dhg 6

迭代者的观点是懒惰.换句话说,当您创建迭代器时,在您去读取数据之前,它不会评估任何内容.这是看起来像:

scala> val itr = List(1,2,3).iterator
itr: Iterator[Int] = non-empty iterator
Run Code Online (Sandbox Code Playgroud)

好的,我们现在有了一个迭代器.但它还没有真正查看清单.

scala> val mappedItr = itr.map((x: Int) => println(x))
mappedItr: Iterator[Unit] = non-empty iterator
Run Code Online (Sandbox Code Playgroud)

现在我们有了一个新的Iterator.当访问数据时,这将应用已映射的函数.但我们没有真正看过原来的清单.

scala> mappedItr.next
1
Run Code Online (Sandbox Code Playgroud)

这是我们第一次访问数据,因此这是Iterator第一次查看列表.我们打电话next,所以我们得到了第一个元素.由于我们的迭代器已经map排队,因此当我们访问该元素时它会应用映射函数.所以我们看到应用于next项目的函数的结果.

我们可以再做一次以获得下一个元素:

scala> mappedItr.next
2
Run Code Online (Sandbox Code Playgroud)

并且,它再次仅在需要时评估函数,以便给出最终结果.