Sono molto nuovo a Scala, quindi perdona la mia ignoranza! Sto cercando di ripetere le coppie di numeri interi che sono limitati da un massimo. Ad esempio, se il massimo è 5, allora l'iterazione dovrebbe restituire:Flusso delimitato dalla coda ricorsiva di coppie di interi (Scala)?
(0, 0), (0, 1), ..., (0, 5), (1, 0), ..., (5, 5)
Ho scelto di cercare di coda ricorsivamente restituire questo come un flusso:
@tailrec
def _pairs(i: Int, j: Int, maximum: Int): Stream[(Int, Int)] = {
if (i == maximum && j == maximum) Stream.empty
else if (j == maximum) (i, j) #:: _pairs(i + 1, 0, maximum)
else (i, j) #:: _pairs(i, j + 1, maximum)
}
Senza l'annotazione tailrec la codice funziona:
scala> _pairs(0, 0, 5).take(11)
res16: scala.collection.immutable.Stream[(Int, Int)] = Stream((0,0), ?)
scala> _pairs(0, 0, 5).take(11).toList
res17: List[(Int, Int)] = List((0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (1,0), (1,1), (1,2), (1,3), (1,4))
Ma questo non è abbastanza buono per me. Il compilatore è correttamente sottolineando che l'ultima linea di _pairs non restituisce _pairs:
could not optimize @tailrec annotated method _pairs: it contains a recursive call not in tail position
else (i, j) #:: _pairs(i, j + 1, maximum)
^
Così, ho alcune domande:
- affrontare direttamente l'attuazione sopra, come si fa ritorno una coda in modo ricorsivo Stream [(Int, Int)]?
- fare un passo indietro, qual è il modo più efficiente di memoria per iterare su sequenze limitate di numeri interi? Non voglio eseguire un'iterazione su Range perché Range extends IndexedSeq e non voglio che la sequenza esista interamente in memoria. O mi sbaglio? Se eseguo iterazioni su Range.view, evito che venga in memoria? (!)
In Python, tutto quello che voglio è:
In [6]: def _pairs(maximum):
...: for i in xrange(maximum+1):
...: for j in xrange(maximum+1):
...: yield (i, j)
...:
In [7]: p = _pairs(5)
In [8]: [p.next() for i in xrange(11)]
Out[8]:
[(0, 0),
(0, 1),
(0, 2),
(0, 3),
(0, 4),
(0, 5),
(1, 0),
(1, 1),
(1, 2),
(1, 3),
(1, 4)]
Grazie per il vostro aiuto! Se pensi che io abbia bisogno di leggere riferimenti/documenti API/qualsiasi altra cosa, ti prego di dirmelo, perché sono desideroso di imparare.
Grazie per la risposta! Capisco perché quello che ho fatto non è ricorsivo della coda, e sicuramente preferirei usare 'for'. Il problema che ho è che 'pair', come hai suggerito, restituisce' IndexedSeq'. Quindi l'intero risultato esisterà in memoria quando viene chiamato 'pairs'. Potresti per favore approfondire come utilizzare le visualizzazioni per evitare questo? –
E avete ulteriori dettagli e riferimenti su flussi e thunk? Sono molto curioso di sapere come non farò esplodere lo stack chiamando ricorsivamente una funzione ottimizzata chiamata non-tail dove non utilizzo le coroutine. Così tanto da imparare! –
@AsimIhsan: Risponderò a queste domande in una modifica. –