Bucle repeat en R

Introducción a R Estructuras de control
Bucle repeat en R

El bucle repeat es un bucle de propósito general en R que itera un bloque de código o proceso indefinidamente hasta que se cumple una condición específica o hasta que el bucle se termina explícitamente utilizando la sentencia break. Es similar, pero diferente, de un bucle for, que itera sobre una secuencia predefinida.

Es importante señalar que, en muchos casos, el bucle for sigue siendo la opción más clara y concisa para la iteración sobre secuencias predefinidas. El uso del bucle repeat suele reservarse para situaciones en las que la lógica del flujo de control es más compleja o en las que se necesita más flexibilidad para determinar la condición de salida.

Sintaxis de repeat

La sintaxis del bucle repeat es la siguiente:

repeat {
  # Código a ser repetido
  if (condition) {
    break  # Termina el bucle si se cumple la condición
  }
}

El bucle repeat evalúa un proceso y lo repite indefinidamente hasta que se evalúa un break.

¡Ten cuidado! Dado que repeat puede crear bucles infinitos, es crucial manejarlos con seguridad. Establece un límite de iteraciones o una condición de salida con break.

Casos de uso de los bucles repeat

Bucles infinitos

Uno de los principales casos de uso de repeat es crear bucles infinitos. Por ejemplo, una simulación que se ejecuta hasta que se cumple una determinada condición (especialmente cuando no se sabe cuántas iteraciones son necesarias para cumplir la condición):

i <- 1

repeat {
  
  # Código a repetir
  print(i)
  i <- i + 1
  
  # Si i > 10 el bucle se detiene
  if (i > 10) {
    break
  }
  
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10

Como se ha dicho antes, estos bucles son útiles cuando no se sabe cuántas iteraciones son necesarias para cumplir una condición específica. En el siguiente escenario un valor se divide por dos hasta que es inferior a un umbral específico y el uso de un bucle repeat puede ser útil o más rápido si no sabes cómo calcular el número de iteraciones necesarias.

valor <- 10
iter <- 1

repeat {
  
  # Código a repetir
  valor <- valor / 2
  
  # Si valor < 0.000000048 el bucle se detiene
  if (valor < 0.000000048) {
    break
  }
  iter <- iter + 1
}

# Resultados
cat("Número de iteraciones:", iter, "\n")
cat("Value:", valor)
Número de iteraciones: 28
Valor: 3.72529e-08

El siguiente es un ejemplo más complejo que genera valores aleatorios uniformes hasta que la suma de ellos es mayor que 5. Como los valores son pseudoaleatorios, el número de iteraciones necesarias para cumplir la condición es impredecible y depende de la secuencia específica de valores generados, reflejando la naturaleza estocástica de la simulación, por lo que un bucle repeat funcionará muy bien en este escenario.

# Semilla para reproducibilidad
set.seed(123)  

iteraciones <- 0
suma_total <- 0

repeat {
  # Generar un número aleatorio entre 0 y 1
  numero_aleatorio <- runif(1)
  
  # Acumular los números aleatorios
  suma_total <- suma_total + numero_aleatorio
  iteraciones <- iteraciones + 1
  
  # Comprobar la condición (por ejemplo, suma total superior a 5)
  if (suma_total > 5) {
    break # Salir del bucle si se cumple la condición
  }
}

# Resultados
cat("Número de iteraciones:", iteraciones, "\n")
cat("Suma total:", suma_total, "\n")
Número de iteraciones: 9
Suma total: 5.32586

Si eliminas o cambias la semilla del ejemplo anterior, el número de iteraciones para cumplir la condición y la suma final de valores podrían variar.

Programas basados en menús

Los bucles repeat también son útiles para programas dirigidos por menús en los que se pide al usuario que haga elecciones hasta que decida salir. El siguiente ejemplo ilustra cómo escribir un bucle repeat que sólo termina cuando el usuario introduce un valor positivo:

# Bucle repeat para validar una entrada de usuario
repeat {
  user_input <- readline("Introduce un número positivo: ")
  user_input <- as.numeric(user_input)
  
  # If input is not NA and greater than 0 stops the loop
  if (!is.na(user_input) && user_input > 0) {
    cat("¡Número válido!\n")
    break
  } else {
    cat("Número no válido. Try again.\n")
  }
}
Introduce un número positivo: -5
Número no válido. Try again.
Introduce un número positivo: NA
Número no válido. Try again.
Introduce un número positivo: 4
¡Número válido!