2014-11-03 77 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