Hemos hablado de la palabra clave retry
al discutir el reintento después de las excepciones. Su poco conocida contraparte redo
funciona de manera similar, pero vuelve a ejecutar iteraciones de bucle en lugar de bloques enteros.
La palabra clave redo
Como aprendimos en el artículo anterior de la Academia, retry
permite reintentar un trozo de código en un bloque:
1 2 3 4 5 6 |
begin puts "Iteration" raise rescue retry end |
Este ejemplo imprime la palabra «Iteración» en la consola antes de lanzar una excepción. Se ejecuta el bloque de rescate, que llama a retry
y vuelve a iniciar el bloque desde el principio. El resultado es que nuestro programa imprime interminablemente Iteration
. La palabra clave redo
le permite lograr un efecto similar al utilizar bucles. Esto es útil en situaciones en las que se necesita reintentar mientras se itera, por ejemplo.
1 2 3 4 |
10.times do |i| puts "Iteration #{i}" redo if i > 2 end |
Esto imprimirá:
1 2 3 4 5 6 7 8 |
$ ruby redo.rb Iteration 0 Iteration 1 Iteration 2 Iteration 3 Iteration 3 Iteration 3 ... |
¿Nota cómo el recuento de iteraciones permanece igual? Retrocederá la ejecución al inicio del bucle. Esta variante del código utilizando retry
imprimirá exactamente la misma salida:
1 2 3 4 5 6 7 8 |
10.times do |i| begin puts "Iteration #{i}" raise if i > 2 rescue retry end end |
Puedes utilizar redo
para implementar el reintento en un bucle. En el siguiente ejemplo tenemos una cola de trabajos. O bien devuelven :success
o :failure
. Seguimos reejecutando la misma iteración del bucle hasta que el trabajo tenga éxito.
1 2 3 |
.each do |job| redo unless job.call == :success end |
Ruby 1.8
El comportamiento de retry
y redo
cambió entre Ruby 1.8 y 1.9. Solían reiniciar la iteración del bucle, pero ambos de forma diferente. A partir de 1.9, retry
sólo funciona con un bloque begin
/rescue
y redo
sólo funciona dentro de bucles.
La palabra clave next
Si quieres pasar a la siguiente iteración del bucle, en lugar de retroceder al inicio de la actual, puedes utilizar next
.
1 2 3 4 5 |
10.times do |i| puts "Iteration #{i}" next if i > 2 puts "Iteration done" end |
Esto imprimirá:
1 2 3 4 5 6 7 8 9 10 |
$ ruby next.rb Iteration 0 Iteration done Iteration 1 Iteration done Iteration 2 Iteration done Iteration 3 Iteration 4 ... |
¿Ves cómo el contador de iteraciones sigue aumentando? En la mayoría de los casos usar next
es lo que quieres. Mira redo
si necesitas un bucle que se ejecute un número exacto de veces o necesitas un manejo de errores al iterar sobre un array.
Esperamos que hayas aprendido algo nuevo sobre cómo rehacer las iteraciones en los bucles y nos encantaría saber qué te ha parecido este artículo (o cualquiera de los otros de la serie AppSignal Academy). Por favor, no dudes en hacernos saber lo que piensas, o si tienes algún tema de Ruby sobre el que te gustaría aprender más.