Scala “<-” per la comprensione
-
04-10-2019 - |
Domanda
ho scoperto che alla Scala ha sempre una "spiegazione naturale" per nulla. Sempre qualcosa come "Ohh, ma questo è solo una funzione chiamata su questo e che oggetto con questo e quello del parametro". In un certo senso, nulla è davvero compilatore-magia così come la conosciamo da altre lingue.
La mia domanda è sul <- operatore utilizzato nel codice seguente:
for(i <- 0 to 10) println(i)
In questo esempio posso vedere che sia riscritto per qualcosa come:
0.to(10).foreach((i:Int)=>println(i))
, ma questo non spiega come il i sono lasciato trasportare in funzione anonima all'interno della funzione foreach. Nel punto in cui si scrive i non è un oggetto, e non ancora una variabile dichiarata. Così che cosa è, e come viene trasportato verso l'interno del foreach?
La mia ipotesi è che ho finalmente scoperto qualcosa che in realtà è magia compilatore
Grazie per il vostro tempo.
Per chiarire, la mia domanda è:. Come funziona il <- lavoro dell'operatore in 1 ° riga di codice dal momento che non è un oggetto su cui può essere chiamato come una funzione
Soluzione
<-
è un simbolo parola chiave lingua definita, come è =>
ma in netto contrasto con ->
(che è un simbolo definito). Perché è parte della grammatica di base Scala, può essere utilizzato per creare attacchi (per la i
nel tuo esempio), che è qualcosa che non può essere fatto da costrutti definiti dall'utente.
Altri suggerimenti
Per aumentare la risposta di Dave, ecco uno schema di traduzione per 'for-comprensioni' dal specifica del linguaggio Scala:
Una comprensione
for (enums) yield e
Esaminae
espressione per ciascun legame generato dagli enumeratori enumerazioni. Una sequenza enumeratore inizia sempre con un generatore; Questo può essere seguito da ulteriori generatori, definizioni valore, o protezioni.Un generatore
p <- e
produce binding da une
espressione che è compensata in qualche modo contro modellop
. Unval p = e
definizione valore associa il nome di valorep
(o più nomi in unp
pattern) al risultato della valutazione dele
espressione. Unif e
guardia contiene un'espressione booleana che limita binding enumerati.Il significato preciso di generatori e guardie è definito da traduzione di invocazioni dei quattro metodi:
map
,filter
,flatMap
eforeach
. Questi metodi possono essere implementati in modo diverso per i diversi tipi di supporto.Lo schema di traduzione è come segue. In una prima fase, ogni generatore
p <- e
, dove p non è inconfutabile (§8.1) per il tipo die
è sostituito dap <- e.filter { case p => true; case _ => false }
Quindi, le seguenti regole vengono applicate più volte fino a quando tutte le comprensioni sono stati eliminato.
A per-la comprensione
for (p <- e) yield e0
è tradotto ine.map { case p => e0 }
.A per-la comprensione
for (p <- e) e0
è tradotto ine.foreach { case p => e0 }
.A per-la comprensione
for (p <- e; p0 <- e0 . . .) yield e00
, dove. . . è un (possibilmente vuoto) sequenza di generatori o protezioni, si traduce a:.
e.flatMap { case p => for (p0 <- e0 . . .) yield e00 }
A per-la comprensione
for (p <- e; p0 <- e0 . . .) e00
dove. . . è un (possibilmente vuoto) sequenza di generatori o protezioni sono convertiti in:
e.foreach { case p => for (p0 <- e0 . . .) e00 }
.A
p <- e
generatore seguito da unif g
guardia viene traslato in un unico generatore:
p <- e.filter((x1, . . . , xn) => g )
dovex1
,. . . ,xn
sono le variabili libere dip
.A
p <- e
generatore seguita da una definizioneval p0 = e0
valore viene tradotto al seguente generatore di coppie di valori, in cuix
ex0
sono nomi freschi:val (p, p0) <- for(x@p <- e) yield { val x0@p0 = e0; (x, x0) }
In questo caso, è davvero un po 'di magia compilatore. La traduzione da per-la comprensione di filtro / carta / modulo flatmap è un po 'speciale di Dezuccheraggio, proprio come la conversione delle forme speciali di aggiornamento e applicare metodi.