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.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.