Como posso devolver algo mais cedo de um bloco?

88

Se eu quisesse fazer algo assim:

collection.each do |i|
   return nil if i == 3

   ..many lines of code here..
end

Como eu conseguiria esse efeito? Eu sei que poderia simplesmente envolver tudo dentro do bloco em uma grande instrução if, mas gostaria de evitar o aninhamento, se possível.

Break não funcionaria aqui, porque não quero interromper a iteração dos elementos restantes.

Ryeguy
fonte

Respostas:

173

nextdentro de um bloco retorna do bloco. breakdentro de um bloco retorna da função que rendeu ao bloco. Pois eachisso significa que breaksai do loop e nextpula para a próxima iteração do loop (daí os nomes). Você pode retornar valores com next valuee break value.

sepp2k
fonte
51
1 para o next valuee break value. Exatamente o que eu estava procurando.
Joshua Pinter
1
break valuenão funcionou para mim, enquanto next valuefuncionou bem. Muito obrigado.
Francesco Belladonna
4
Não tenho certeza se sua definição de próximo e intervalo está correta. No mínimo, eles são confusos. break sai do loop mais interno, next move você para a próxima iteração. fonte: tutorialspoint.com/ruby/ruby_loops.htm
WattsInABox
3
@WattsInABox nexte não breaksão de forma alguma específicos para construções de loop, então o artigo que você vinculou é muito enganoso (uma vez que implica fortemente o oposto). E minhas descrições estão definitivamente corretas quando nexte breaksão usadas dentro de blocos (observe que whilee forraramente, ou nunca, são usadas em Ruby, então 99% dos usos de nexte breakestão dentro de blocos).
sepp2k
Eu acho que você quer dizer blocos sem loop. É isso que está confuso. Além disso, discordo da sua afirmação de 99%, mas esse é um argumento diferente.
WattsInABox de
11
#!/usr/bin/ruby

collection = [1, 2, 3, 4, 5 ]

stopped_at = collection.each do |i|
   break i if i == 3

   puts "Processed #{i}"
end

puts "Stopped at and did not process #{stopped_at}"
JD.
fonte
5

Neste caso, você pode usar break para encerrar o loop mais cedo:

collection.each do |i|
  break if i == 3
  ...many lines
end

... claro, isso pressupõe que você não está realmente procurando retornar um valor, apenas sair do bloco.

Sniggerfardimungus
fonte
Isso não iria apenas retornar do bloco, ele iria retornar de cada um. Portanto, o loop terminaria, não continuaria com o próximo valor. Não tenho certeza se é isso que se pretende.
sepp2k
3
Você pode usar um valor com breakem Ruby - break 5fará com eachque retorne 5.
Chuck
1
Obrigado, mas não quero interromper a iteração.
ryeguy,