Die tailrec-Annotation
Garantierte Optimierung
Die tailrec-Annotation ist eine kostenlose Scala for Backend Engineering & Functional Programming-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Scala for Backend Engineering & Functional Programming-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 4 Lektionen.
Was ist Endrekursion?
Ein rekursiver Aufruf befindet sich in Endposition, wenn er die allerletzte Aktion der Funktion ist. Eine endrekursive Funktion kann zu einer Schleife optimiert werden, die einen einzigen Stack-Frame wiederverwendet, sodass kein Überlauf auftritt.
Endposition
In n * factorial(n-1) ist der rekursive Aufruf nicht der letzte Schritt: Die Multiplikation findet statt, nachdem er zurückgekehrt ist. In gcd(b, a % b) ist der Aufruf der letzte Schritt. Nur der zweite Fall ist endrekursiv.
Die Annotation @tailrec
Importieren Sie scala.annotation.tailrec und annotieren Sie eine Methode. Der Compiler prüft dann, ob sich der Aufruf tatsächlich in Endposition befindet, und wendet die Optimierung an. Ist dies nicht der Fall, schlägt die Kompilierung fehl.
import scala.annotation.tailrec
object Main {
@tailrec
def countdown(n: Int): Unit = {
if (n >= 0) {
println(n)
countdown(n - 1)
}
}
def main(args: Array[String]): Unit = countdown(3)
}Garantierte Optimierung
Der wichtigste Vorteil von @tailrec ist die Garantie zur Compile-Zeit. Sie erfahren sofort, wenn Ihre Funktion nicht stapelsicher ist, statt dies erst durch einen Laufzeitabsturz bei einer großen Eingabe festzustellen.
Eine endrekursive gcd
Der euklidische Algorithmus ist bereits endrekursiv: Der rekursive Aufruf ist das gesamte Ergebnis des Funktionskörpers. Durch die Annotation wird dies bestätigt.
import scala.annotation.tailrec
object Main {
@tailrec
def gcd(a: Int, b: Int): Int =
if (b == 0) a else gcd(b, a % b)
def main(args: Array[String]): Unit = {
println(gcd(1071, 462))
}
}Was die Endposition aufhebt
Häufige Muster, die den Aufruf aus der Endposition verschieben:
- Arithmetik mit dem Ergebnis:
n + f(...). - Einpacken in einen Konstruktor:
x :: f(...). - Verwendung des Ergebnisses in einem
try-Block.
Beispiel ohne Endrekursion
Diese Summe ist nicht endrekursiv, weil die Addition den Aufruf umschließt. Eine Annotation mit @tailrec würde einen Kompilierungsfehler verursachen. (Sie wird ohne Annotation gezeigt, damit sie ausgeführt werden kann.)
object Main {
def sum(n: Int): Int =
if (n == 0) 0
else n + sum(n - 1)
def main(args: Array[String]): Unit = {
println(sum(100))
}
}Warum dies nicht optimiert werden kann
Da n + sum(n - 1) den Wert n speichern muss, um die Addition nach der Rückkehr des Aufrufs abzuschließen, benötigt jede Ebene ihren eigenen Stack-Frame. Der Compiler kann dies nicht zu einer Schleife zusammenfassen, daher ist die Funktion nicht endrekursiv.
Eine große endrekursive Schleife
Eine endrekursive Summe mit einem Akkumulator kann für sehr große Eingaben ausgeführt werden, ohne einen Überlauf zu verursachen, da sie einen einzigen Frame wiederverwendet.
import scala.annotation.tailrec
object Main {
@tailrec
def sumTo(n: Int, acc: Long = 0): Long =
if (n == 0) acc else sumTo(n - 1, acc + n)
def main(args: Array[String]): Unit = {
println(sumTo(1000000))
}
}tailrec erfordert final oder lokal
Damit @tailrec angewendet werden kann, darf die Methode nicht überschreibbar sein: Sie muss private, final oder eine lokale bzw. verschachtelte Methode sein. Eine offene Methode könnte überschrieben werden, wodurch die Optimierung ungültig würde; deshalb weist der Compiler sie zurück.
Besonderheit bei gegenseitiger Rekursion
@tailrec optimiert nur eine Funktion, die sich selbst aufruft. Zwei Funktionen, die sich gegenseitig aufrufen (gegenseitige Rekursion), können von der JVM nicht direkt endrekursiv optimiert werden; dafür benötigen Sie Trampolining, das später behandelt wird.
Kurztest
Testen Sie Ihr Verständnis von @tailrec.
Zusammenfassung
Sie haben die Annotation @tailrec kennengelernt:
- Ein Aufruf in Endposition kann zu einer Schleife optimiert werden.
@tailrecgarantiert zur Compile-Zeit die Stapelsicherheit.- Die Methode muss
final,privateoder lokal sein. - Die Annotation gilt nur für Selbstrekursion, nicht für gegenseitige Rekursion.
Lerne Scala mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 39
- Lektionen
- 143
Häufig gestellte Fragen
Ist die Lektion „Die tailrec-Annotation“ kostenlos?
Ja — der vollständige Text von „Die tailrec-Annotation“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Scala for Backend Engineering & Functional Programming-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Die tailrec-Annotation“?
Garantierte Optimierung Du übst Scala for Backend Engineering & Functional Programming mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Scala for Backend Engineering & Functional Programming zu starten?
Keine Vorkenntnisse erforderlich. Scala for Backend Engineering & Functional Programming auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.
Wie lange dauert die Lektion „Die tailrec-Annotation“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Scala for Backend Engineering & Functional Programming-Lektion Code schreiben und ausführen?
Ja. Jede Scala for Backend Engineering & Functional Programming-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Rekursionsgrundlagen
- Die tailrec-Annotation
- Akkumulator-Muster
- Trampolining