Java supporta e ottimizza le chiamate ricorsive in coda?

Diciamo che ho una funzione ricorsiva che è ricorsiva in coda.

System.out.println( sum(Arrays.asList(0, 1, 2, 3, 4, 5)) ); int sum(List integers) { if (integers.isEmpty()) return 0; else return integers.get(0) + sum(integers.subList(1, integers.size())); } 

Mi chiedo se questa sum funzioni crescerà sullo stack o verrà modificata in un ciclo (poiché è una funzione ricorsiva di coda)?

Ho appena letto che Scala rileva tali chiamate e la ottimizza ma è una cosa solo Scala o JVM in generale?

Java supporta le chiamate ricorsive in coda, ma AFAIK non le ottimizza. Penso che sia il compilatore di Scala che è semplicemente capace di questo, non della stessa JVM. Controlla l’annotazione @tailrec in Scala per vedere di più di quanto è capace il compilatore 🙂

Ma indipendentemente dal fatto che Java / JVM ottimizzi la ricorsione in coda, la tua funzione sarebbe più difficile da ottimizzare del necessario.

Guarda questo:

 int sum(List integers) { return sum(integers, 0); } int sum(List integers, int sumSoFar) { if (integers.isEmpty()) return sumSoFar; else return sum( integers.subList(1, integers.size()), sumSoFar + integers.get(0) ); } 

Vedi, ho aggiunto una sum sovraccaricata con un parametro sum calcasting così lontano. In questo modo, quando ti ritrovi nel ramo else , non hai più bisogno del frame dello stack effettivo: hai tutto ciò che ti serve come argomenti della funzione nella chiamata ricorsiva.

Nello snippet, probabilmente il frame dello stack dovrebbe esistere fintanto che la chiamata ricorsiva ..

Secondo questo articolo da aprile 2014:

È importante notare che questo non è un bug nella JVM. È un’ottimizzazione che può essere implementata per aiutare i programmatori funzionali che usano la ricorsione, che è molto più comune e normale in quelle lingue. Recentemente ho parlato con Brian Goetz di Oracle di questa ottimizzazione, e ha detto che è in una lista di cose da aggiungere alla JVM, ma non è un elemento prioritario.