2014-11-03 109 views
10

我对scala中的理解效率有疑问。scala中的理解性能

这下面的代码需要大约45秒时的烫发是大约550元素

perm = some list 
for{ 
    perm <- perms.withFilter(_.size > 0) 
    wordList = somefunction(perm) //expensive operation, wordlist is a list of strings 
    sentenceList = somefunction1(perm) //very expensive operation, sentenceList is a list of list of strings 
    word <- wordList 
    sentence <- sentenceList 
} yield { word::sentence} 

当我改变下面的代码到下面的列表来运行,它在3秒跑用相同的烫发列表

perm = some list 
for{ 
    perm <- perms.withFilter(_.size > 0) 
    word <- somefunction(perm) //expensive operation 
    sentence <- somefunction1(perm) //very expensive operation 
} yield { word::sentence} 

性能的差异是否与Scala中的懒惰评估有关?

回答

10

让我们desugar既为-推导:

1)

perms.withFilter(_.size > 0).flatMap { perm => 
    val wordList = somefunction(perm) //expensive operation 
    val sentenceList = somefunction1(perm) //very expensive operation 
    wordList.flatMap { word => 
    sentenceList.map { sentence => 
     word::sentence 
    } 
    } 
} 

2.)

perms.withFilter(_.size > 0).flatMap { perm => 
    somefunction(perm).flatMap { word => 
    somefunction1(perm).map { sentence => 
     word :: sentence 
    } 
    } 
} 

在第一种情况下,既昂贵功能将被每次执行。在第二种情况下,当somefunction(perm)返回空结果时,somefunction1(perm)将不会执行。

+0

感谢您的回答。我明白你的意思。我有一个跟进关于脱糖过程的问题。为什么第一条语句写成'perms.withFilter(_。size> 0).flatMap {}'而不是'perms.withFilter(_。size> 0).foreach {}'? – Piyush 2014-11-03 18:10:34

+1

'foreach'返回'Unit',所以你的结果将会丢失。 – drexin 2014-11-03 21:26:54

+0

啊,我明白了。那么对于{x < - x1,y <-y1,z <-z1} yield(x ::: y ::: z)的以下for-comprehensions转换为x1.flatmap {x => y1。 flatmap {y => z1.map {z => x :: y :: z}}}'? – Piyush 2014-11-03 21:54:21

0

在你的第一个片段中,看起来你正在“循环”你的每一件物品,实际上,笛卡尔产品。

但是,在你的第二个片段中,你只是用循环“循环”每个项目在一个“单词”烫发。所以我认为这会快很多?

我似乎无法确定变量的完整类型,所以很难完全解释。

+0

wordlist是一个字符串列表,senetenceList是一个字符串列表列表。 – Piyush 2014-11-03 17:56:58