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 syntax puede ser incorrecta), que utiliza una etiqueta de bucle para romper el bucle externo desde el interior del bucle. ¿Hay algo similar en Ruby?
Lo que desea es flujo de control no local, que Ruby tiene varias opciones para hacer:
throw
/ catch
Continuaciones
Pros:
GOTO
. Contras:
Excepciones
Pros:
Contras:
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:
StopIteration
para la terminación. Contras:
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
No, no hay.
Tus opciones son:
while c1 while c2 do_break=true end next if do_break end
o “romper si do_break” dependiendo de lo que quieras
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.
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.
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