2009-09-06 16 views
19

Quando ho iniziato a guardare Scala, mi è piaciuto l'aspetto delle incomprensioni. Sembravano un po 'come i cicli foreach a cui ero abituato da Java 5, ma con restrizioni funzionali e molta dolcezza sintattica.Le incomprensioni di Scala: caratteristica vitale o zucchero sintattico?

Ma, come ho assorbito lo stile di Scala, trovo che ogni volta che potrebbe utilizzare un per-comprension sto usando map, flatMap, filter, reduce e foreach invece. L'intenzione del codice mi sembra più chiara in questo modo, con meno potenziali sorprese nascoste, e di solito sono anche codice più corto.

Per quanto ne so, le incomprensioni sono sempre compilate in questi metodi comunque, quindi mi chiedo: per cosa sono effettivamente? Mi manca qualche rivalutazione funzionale (non sarebbe la prima volta)? Le incomprensioni fanno qualcosa che le altre caratteristiche non possono o dovrebbero essere perlomeno più goffi? Brillano sotto un particolare caso d'uso? È davvero solo una questione di gusti personali?

+2

Questo è quasi un duplicato di http://stackoverflow.com/questions/1052476/can-qualcuno-spiegare-Scalas-rendimento. Quella domanda si chiedeva che cosa fosse "yield", questo si chiede quale sia il suo scopo. Le risposte sono circa le stesse. –

risposta

13

Si prega di fare riferimento a this question. La risposta breve è che le incomprensioni possono essere più leggibili. In particolare, se disponi di molti generatori annidati, la portata effettiva di ciò che stai facendo diventa più chiara e non hai bisogno di grossi rientri.

10

per la comprensione è zucchero sintattico, ma ciò non significa che non siano vitali. Di solito sono più concisi rispetto alla loro forma espansa, il che è bello, ma forse, cosa più importante, aiutano i programmatori di linguaggi imperativi a utilizzare i costrutti funzionali.

Quando ho iniziato per la prima volta con Scala, ho usato molte cose per capire perché erano familiari. Poi mi sono quasi fermato completamente, perché sentivo che usare i metodi sottostanti era più esplicito e quindi più chiaro. Ora sono tornato a usare le incomprensioni perché ritengo che esprimano meglio l'intento di ciò che sto facendo piuttosto che i mezzi per farlo.

3

Hai ragione. La comprensione finale è zucchero sintattico. Credo che i metodi alla base siano più succinti e più facili da leggere, una volta che vi siete abituati.

Confrontare le seguenti affermazioni equivalenti:

1. for (i <- 1 to 100; if (i % 3 == 0)) yield Math.pow(i, 2) 
2. (1 to 100).filter(_ % 3 == 0).map(Math.pow(_, 2)) 

A mio parere, l'aggiunta del punto e virgola a # 1 distrae dal senso che si tratta di una singola istruzione incatenato. C'è anche la sensazione che io sia una var (è 1, o è 99, o qualcosa in mezzo?) Che toglie uno stile altrimenti funzionale.

L'opzione 2 è più chiaramente una catena di richiami di metodo sugli oggetti. Ogni link della catena afferma chiaramente la propria responsabilità. Non ci sono variabili intermedie.

Forse per le comprensioni sono inclusi come una comodità per gli sviluppatori che passano da Java. Indipendentemente da ciò, che viene scelto è una questione di stile e preferenza.

+0

"una volta abituati a loro" - esattamente. Una volta che ho capito le monadi, sono passato ai metodi di base. La comprensione per la comprensione era un collegamento utile prima di quello. –

+1

Non è necessario alcun punto e virgola in 1: 'for (i <- 1 a 100 if (i% 3 == 0)) restituiscono Math.pow (i, 2)'. Inoltre, è possibile sostituire le parentesi con parentesi per attivare l'inferenza del punto e virgola. – Blaisorblade

+0

Grazie @Blaisorblade Mi chiedo se il punto e virgola fosse necessario nel 2009. – Synesso

11

Un altro grande uso della comprensione è per DSL interno. ScalaQL è un grande esempio di questo. Si può trasformare questo

val underAge = for { 
    p <- Person 
    c <- Company 
    if p.company is c 
    if p.age < 14 
} yield p 

in questo

SELECT p.* FROM people p JOIN companies c ON p.company_id = c.id WHERE p.age < 14 

e molto altro ancora.

+0

@Erik Ha funzionato quando l'ho provato. È un collegamento a un file PDF. Se non riesci ancora a scaricare il file, google it: ScalaQL: query di database integrate in linguaggio per Scala di Daniel Spiewak e Tian Zhao –

+0

Downvoted: la vera domanda è se c'è qualche vantaggio di comprensione per il loro desugaring - e puoi scrivere quel codice anche in forma desugared. ScalaQuery è un esempio migliore, poiché ha un'implementazione di qualità di produzione disponibile. Quel foglio lascia intravedere troppi dettagli importanti da raccomandare. – Blaisorblade

5

In alcuni casi, le comprensioni possono esprimere meglio l'intento, quindi quando lo fanno, usale.

Si noti inoltre che con la comprensione, si ottiene modello corrispondente gratuitamente. Ad esempio, l'iterazione di una mappa è molto più semplice con la comprensione:

for ((key, value) <- map) println (key + "-->" + value)

che con foreach:

map foreach { case (key, value) => println (key + "-->" + value) }

Problemi correlati