0Pricing
Scala for Backend Engineering & Functional Programming · Lección

La anotación tailrec

Optimización garantizada

La anotación tailrec es una lección gratuita de Scala for Backend Engineering & Functional Programming en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Scala for Backend Engineering & Functional Programming, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.

Partes de esta lección aún no han sido traducidas y se muestran en inglés.

What is Tail Recursion?

A recursive call is in tail position when it is the very last action of the function. A tail-recursive function can be optimized into a loop, reusing a single stack frame, so it never overflows.

Tail Position

In n * factorial(n-1), the recursive call is not last: the multiplication happens after it returns. In gcd(b, a % b), the call is last. Only the latter is tail-recursive.

The @tailrec Annotation

Import scala.annotation.tailrec and annotate a method. The compiler then verifies the call is truly in tail position and applies the optimization. If it is not, compilation fails.

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

Guaranteed Optimization

The key benefit of @tailrec is the compile-time guarantee. You are told immediately if your function is not stack-safe, rather than discovering it via a runtime crash on large input.

A Tail-Recursive gcd

Euclid's algorithm is already tail-recursive: the recursive call is the entire body's result. Annotating it confirms this.

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

What Breaks Tail Position

Common patterns that move the call out of tail position:

  • Doing arithmetic on the result: n + f(...).
  • Wrapping in a constructor: x :: f(...).
  • Using the result in a try block.

Non-Tail Example

This sum is not tail-recursive because the addition wraps the call. Annotating it with @tailrec would cause a compile error. (Shown without the annotation so it runs.)

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

Why It Cannot Be Optimized

Because n + sum(n - 1) must remember n to finish the addition after the call returns, each level needs its own stack frame. The compiler cannot collapse this into a loop, so it is not tail-recursive.

A Large Tail-Recursive Loop

A tail-recursive sum using an accumulator runs for huge inputs without overflowing, because it reuses one frame.

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 Requires final or Local

For @tailrec to apply, the method must not be overridable: it must be private, final, or a local/nested method. An open method could be overridden, breaking the optimization, so the compiler rejects it.

Mutual Recursion Caveat

@tailrec only optimizes a function calling itself. Two functions calling each other (mutual recursion) cannot be tail-optimized by the JVM directly; for that you need trampolining, covered later.

Quick Check

Test your understanding of @tailrec.

Recap

You learned the @tailrec annotation:

  • A call in tail position can be optimized into a loop.
  • @tailrec gives a compile-time guarantee of stack safety.
  • The method must be final, private, or local.
  • It only covers self-recursion, not mutual recursion.

Preguntas frecuentes

¿La lección «La anotación tailrec» es gratis?

Sí — el texto completo de «La anotación tailrec» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Scala for Backend Engineering & Functional Programming, actualiza a CoddyKit PRO. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.

¿Qué aprenderé en «La anotación tailrec»?

Optimización garantizada Practicas Scala for Backend Engineering & Functional Programming con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Scala for Backend Engineering & Functional Programming?

No se requiere experiencia previa. Scala for Backend Engineering & Functional Programming en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «La anotación tailrec»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Scala for Backend Engineering & Functional Programming?

Sí. Cada lección de Scala for Backend Engineering & Functional Programming incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Conceptos básicos de recursión
  2. La anotación tailrec
  3. Patrón acumulador
  4. Trampolining
← Volver a Scala for Backend Engineering & Functional Programming