Scala有一种将集合转换为另一个集合的惊人方式 地图构造。
if (wordsProcessed == numOfPuzzl) {
printf("\n");
while ( fgets(myString, 256, pFile) != NULL ){
if ( sscanf(myString, "%d", &numOfPuzzl) == 1 )
break;
}
wordsProcessed = 0;
}
将返回列表val l = List(1, 2, 3, 4)
l.map(_*_)
我遇到了多个地图链接在一起的各种情况,例如
l
我认为在下面发生的事情等同于以下内容。
val l = List(1, 2, 3, 4)
val res = l.map(_ * _).map(_ + 1).filter(_ < 3)
如果集合太大,创建val l = List(1, 2, 3, 4)
val l1 = l.map(_*_)
val l2 = l1.map(_ + 1)
val res = l2.filter(_ < 3)
和l1
可能会导致内存问题。
要解决这个问题,Scala编译器是否有任何优化?
l2
一般情况下val l = List(1, 2, 3, 4)
val res = l1.map( _*_ + 1).filter(_ < 3)
,f
,g
是函数
h
可以转换为
val l = List(/*something*/)
val res = l.map(f(_)).map(g(_)).map(h(_))
答案 0 :(得分:3)
Scala提供Stream
,这是一个懒惰的有序集合。
val s = Stream(1, 2, 3, 4)
// note i've changed your sequence of transformations
// a bit, so that it compiles and yields more than one result
val res = s.map(i => i * i).map(_ + 1).filter(_ < 11)
res
现在是Stream
。尚未执行任何实际评估,未使用与s
大小相关的内存块。
如果您打算一次使用res
个元素,则无需再进行任何工作。例如,您可以直接在for语句或理解中使用res
。
for ( elem <- res ) println( s"A value is ${elem}" )
如果您希望res
为List
,则可以在转换序列结束时调用.toList
。而不是上述,使用
val res = s.map(i => i * i).map(_ + 1).filter(_ < 11).toList
s
只会在创建新List
时遍历一次。
答案 1 :(得分:0)
不,因为这需要编译器知道map
的语义并且特别对待实现它的标准库类(因为没有人阻止你编写一个没有这个的类) 。有一个research proposal可能最终会实现这个......最终。
还有Scala-Blitz优化了一些收集操作,但融合和砍伐森林被列为this presentation中的未来工作,我认为它们尚未实施。
正如Steve Waldman的回答所说,使用Stream
(或者,更好的是Iterator
)可以提供帮助,但它不会完全消除中间集合。