Sono confuso dal seguente codice: il codice è artificiale, ma continuo a pensare che sia ricorsivo in coda. Il compilatore non è d'accordo e produce un messaggio di errore:Perché il ritorno in getOrElse non rende possibile la ricorsione in coda?
@annotation.tailrec
def listSize(l : Seq[Any], s: Int = 0): Int = {
if (l.isEmpty) {
None.getOrElse(return s)
}
listSize(l.tail, s + 1)
}
Come è possibile che il codice sopra non renda possibile la codifica della coda? Perché il compilatore mi dice:
could not optimize @tailrec annotated method listSize: it contains a recursive call not in tail position
Un codice simile (con return
interno map
) compila bene:
@annotation.tailrec
def listSize(l : Seq[Any], s: Int = 0): Int = {
if (l.isEmpty) {
Some(()).map(return s)
}
listSize(l.tail, s + 1)
}
Anche il codice ottenuto con inlining None.isEmpty
compila bene:
@annotation.tailrec
def listSize(l : Seq[Any], s: Int = 0): Int = {
if (l.isEmpty) {
if (None.isEmpty) {
return s
} else None.get
}
listSize(l.tail, s + 1)
}
D'altra parte, il codice con la mappa leggermente modificata è rifiutato dalla compilation er e produce l'errore:
@annotation.tailrec
def listSize(l : Seq[Any], s: Int = 0): Int = {
if (l.isEmpty) {
Some(()).map(x => return s)
}
listSize(l.tail, s + 1)
}
Ho la sensazione che il compilatore non possa decidere se il tuo metodo è ricorsivo in coda a causa dell'istruzione return, probabilmente è difensivo e ti dice che la ricorsione non è garantita. –