2014-11-03 12 views
10

Ho una domanda sull'efficienza delle incomprensioni in scala.Prestazioni di comprensione per scala

Questo seguente codice richiede circa 45 secondi per eseguire quando perm è un elenco di circa 550 elementi

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} 

quando ho cambiato il seguente codice nel seguito, ha funzionato in 3 sec con l'elenco stesso perm

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

La differenza nell'esecuzione ha qualcosa a che fare con la valutazione pigra in Scala?

risposta

10

Let sia per-comprensioni:

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 
    } 
    } 
} 

Nel primo caso, entrambe le funzioni costosi verrà eseguito ogni volta. Nel secondo caso, quando somefunction(perm) restituisce un risultato vuoto, somefunction1(perm) non verrà mai eseguito.

+0

Grazie per la risposta. Vedo il tuo punto. Ho una domanda di follow-up sul processo di de-sugaring. Perché la prima istruzione è scritta come 'perms.withFilter (_. Size> 0) .flatMap {}' e non 'perms.withFilter (_. Size> 0). Foreach {}'? – Piyush

+1

'foreach' restituisce' Unità', quindi il risultato sarebbe perso. – drexin

+0

Ah, capisco. Così il seguente for-comprehensions 'for {x <- x1, y <-y1, z <-z1} yield (x ::: y ::: z)' traduce in 'x1.flatmap {x => y1. flatmap {y => z1.map {z => x :: y :: z}}}}? – Piyush

0

Nel tuo primo frammento, sembra che tu stia "scorrendo" attraverso ogni oggetto che hai nel perm con ogni elemento nel tuo elenco di parole; In effetti, un prodotto cartesiano.

Tuttavia, nel secondo frammento, si esegue il "looping" di ogni elemento in perm con una sola "parola". Quindi presumo che sarebbe molto più veloce?

Non riesco a capire tutti i tipi di variabili, quindi è abbastanza difficile essere in grado di spiegare pienamente. desugar

+0

wordlist è un elenco di stringhe, senetenceList è un elenco di stringhe. – Piyush

Problemi correlati