while until unless true for example ciclo ruby loops cycle

until - if unless ruby



Cómo romper el ciclo exterior en Ruby? (8)

Considera throw/catch . Normalmente, el ciclo externo del código siguiente se ejecutará cinco veces, pero con throw puedes cambiarlo a lo que quieras, rompiéndolo en el proceso. Considera este código ruby ​​perfectamente válido:

catch (:done) do 5.times { |i| 5.times { |j| puts "#{i} #{j}" throw :done if i + j > 5 } } end

En Perl, existe la capacidad de romper un ciclo externo como este:

AAA: for my $stuff (@otherstuff) { for my $foo (@bar) { last AAA if (somethingbad()); } }

(la sintaxis puede ser incorrecta), que utiliza una etiqueta de bucle para romper el bucle externo desde el interior del bucle. ¿Hay algo similar en Ruby?


Envolver un método interno alrededor de los bucles podría hacer el truco Ejemplo:

test = [1,2,3] test.each do |num| def internalHelper for i in 0..3 for j in 0..3 puts "this should happen only 3 times" if true return end end end end internalHelper end

Aquí puede hacer una comprobación dentro de cualquiera de los bucles for y regresar desde el método interno una vez que se cumple una condición.


Lo que desea es flujo de control no local, que Ruby tiene varias opciones para hacer:

  • Continuaciones,
  • Excepciones, y
  • throw / catch

Continuaciones

Pros:

  • Las continuas son el mecanismo estándar para el flujo de control no local. De hecho, puedes construir cualquier flujo de control no local (subrutinas, procedimientos, funciones, métodos, corutinas, máquinas de estado, generadores, condiciones, excepciones) encima de ellos: son más o menos el gemelo más agradable de GOTO .

Contras:

  • Las continuas no son una parte obligatoria de Ruby Language Specification, lo que significa que algunas implementaciones (XRuby, JRuby, Ruby.NET, IronRuby) no las implementan. Entonces, no puedes confiar en ellos.

Excepciones

Pros:

  • Hay un documento que demuestra matemáticamente que las Excepciones pueden ser más poderosas que las Continuaciones. IOW: pueden hacer todo lo que las continuaciones pueden hacer, y más, para que pueda usarlos como reemplazo de las continuaciones.
  • Las excepciones están disponibles universalmente.

Contras:

  • Se llaman "excepciones", lo que hace que las personas piensen que son "solo por circunstancias excepcionales". Esto significa tres cosas: alguien que lea su código podría no entenderlo, la implementación podría no estar optimizada para eso (y, sí, las excepciones son tontas, lentas en casi cualquier implementación de Ruby) y lo peor de todo es que se cansará de todas esas personas constantemente, balbuceando sin pensar "las excepciones son solo para circunstancias excepcionales", tan pronto como echen un vistazo a su código. (Por supuesto, ni siquiera tratarán de entender lo que estás haciendo).

throw / catch

Esto es (más o menos) lo que se vería:

catch :aaa do stuff.each do |otherstuff| foo.each do |bar| throw :aaa if somethingbad end end end

Pros:

  • Lo mismo que las excepciones.
  • En Ruby 1.9, ¡el uso de excepciones para control-flow es en realidad parte de la especificación del lenguaje ! Bucles, enumeradores, iteradores y todos usan una excepción StopIteration para la terminación.

Contras:

  • La comunidad de Ruby los odia incluso más que el uso de excepciones para control-flujo.

No, no hay.

Tus opciones son:

  • poner el lazo en un método y usar retorno para romper desde el bucle externo
  • establecer o devolver una bandera desde el bucle interno y luego verificar esa bandera en el bucle externo y romperla cuando se establece la bandera (lo cual es algo engorroso)
  • usa throw / catch para salir del lazo

Puede considerar agregar un indicador, que se establece dentro del bucle interno, para controlar el bucle externo.

''siguiente'' el bucle externo

for i in (1 .. 5) next_outer_loop = false for j in (1 .. 5) if j > i next_outer_loop = true if j % 2 == 0 break end puts "i: #{i}, j: #{j}" end print "i: #{i} " if next_outer_loop puts "with ''next''" next end puts "withOUT ''next''" end

''romper'' el bucle externo

for i in (1 .. 5) break_outer_loop = false for j in (1 .. 5) if j > i break_outer_loop = true if i > 3 break end puts "i: #{i}, j: #{j}" end break if break_outer_loop puts "i: #{i}" end


Quizás esto es lo que quieres? (no probado)

stuff.find do |otherstuff| foo.find do somethingbad() && AAA end end

El método de búsqueda sigue dando vueltas hasta que el bloque devuelve un valor no nulo o se golpea el final de la lista.


Sé que me arrepentiré de esto en la mañana, pero el simple hecho de usar un ciclo while podría hacer el truco.

x=0 until x==10 x+=1 y=0 until y==10 y+=1 if y==5 && x==3 x,y=10,10 end end break if x==10 puts x end

El if y==5 && x==3 es solo un ejemplo de una expresión que se convierte en verdadera.


while c1 while c2 do_break=true end next if do_break end

o "romper si do_break" dependiendo de lo que quieras