Scala voor backend-engineering en functioneel programmeren · Les

De annotatie tailrec

Gegarandeerde optimalisatie

Les 2 van 413 stappen

De annotatie tailrec is een gratis Scala voor backend-engineering en functioneel programmeren-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Scala voor backend-engineering en functioneel programmeren. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Scala voor backend-engineering en functioneel programmeren bevat in totaal 4 lessen.

Wat is staartrecursie

Een recursieve aanroep staat in de staartpositie wanneer dit de allerlaatste actie van de functie is. Een staartrecursieve functie kan worden geoptimaliseerd tot een lus die één stackframe hergebruikt en daardoor nooit overloopt.

Staartpositie

In n * factorial(n-1) is de recursieve aanroep niet de laatste actie: de vermenigvuldiging vindt plaats nadat de aanroep terugkeert. In gcd(b, a % b) is de aanroep wel de laatste actie. Alleen de tweede functie is staartrecursief.

De annotatie @tailrec

Importeer scala.annotation.tailrec en annoteer een methode. De compiler controleert dan of de aanroep echt in de staartpositie staat en past de optimalisatie toe. Als dat niet zo is, mislukt het compileren.

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)
}

Gegarandeerde optimalisatie

Het belangrijkste voordeel van @tailrec is de garantie tijdens het compileren. Je krijgt meteen te horen dat je functie niet stackveilig is, in plaats van dit pas te ontdekken door een crash tijdens uitvoering met grote invoer.

Een staartrecursieve gcd

Het algoritme van Euclides is al staartrecursief: de recursieve aanroep vormt het volledige resultaat van de funct body. Door de annotatie toe te voegen bevestig je dit.

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))
  }
}

Wat de staartpositie doorbreekt

Veelvoorkomende patronen die de aanroep uit de staartpositie halen:

  • Rekenen met het resultaat: n + f(...).
  • Inpakken in een constructor: x :: f(...).
  • Het resultaat gebruiken in een try-blok.

Niet-staartrecursief voorbeeld

Deze som is niet staartrecursief, omdat de optelling de aanroep omhult. Als je er @tailrec aan toevoegt, ontstaat een compileerfout. (De annotatie is weggelaten zodat het voorbeeld werkt.)

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))
  }
}

Waarom optimalisatie niet mogelijk is

Omdat n + sum(n - 1) n moet onthouden om de optelling af te ronden nadat de aanroep terugkeert, heeft elk niveau zijn eigen stackframe nodig. De compiler kan dit niet tot een lus samenvouwen, dus de functie is niet staartrecursief.

Een grote staartrecursieve lus

Een staartrecursieve som met een accumulator werkt voor enorme invoer zonder over te lopen, omdat één frame wordt hergebruikt.

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 vereist final of lokaal

Om @tailrec te kunnen gebruiken, mag de methode niet overschrijfbaar zijn: de methode moet private, final of lokaal/genest zijn. Een open methode kan worden overschreven, waardoor de optimalisatie niet gegarandeerd is; daarom weigert de compiler deze.

Kanttekening bij wederzijdse recursie

@tailrec optimaliseert alleen een functie die zichzelf aanroept. Twee functies die elkaar aanroepen (wederzijdse recursie) kunnen niet rechtstreeks door de JVM worden geoptimaliseerd voor staartrecursie; daarvoor heb je trampolines nodig, die later aan bod komen.

Korte toets

Toets je begrip van @tailrec.

Samenvatting

Je hebt de annotatie @tailrec geleerd:

  • Een aanroep in de staartpositie kan worden geoptimaliseerd tot een lus.
  • @tailrec geeft tijdens het compileren een garantie op stackveiligheid.
  • De methode moet final, private of lokaal zijn.
  • De annotatie geldt alleen voor zelfrecursie, niet voor wederzijdse recursie.
Gratis beginnen

Leer Scala met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
39
Lessen
143

Veelgestelde vragen

Is de les “De annotatie tailrec” gratis?

Ja — de volledige tekst van “De annotatie tailrec” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Scala voor backend-engineering en functioneel programmeren wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Scala voor backend-engineering en functioneel programmeren bevat in totaal 4 lessen.

Wat leer ik in “De annotatie tailrec”?

Gegarandeerde optimalisatie Je oefent met Scala voor backend-engineering en functioneel programmeren door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Scala voor backend-engineering en functioneel programmeren te beginnen?

Ervaring vooraf is niet nodig. Scala voor backend-engineering en functioneel programmeren op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.

Hoe lang duurt de les “De annotatie tailrec”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Scala voor backend-engineering en functioneel programmeren?

Ja. Elke les over Scala voor backend-engineering en functioneel programmeren bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. De basis van recursie
  2. De annotatie tailrec
  3. Accumulatorpatroon
  4. Trampolining
← Terug naar Scala voor backend-engineering en functioneel programmeren