O Ruby possui dois mecanismos de exceção diferentes: Throw / Catch e Raise / Rescue.
Por que nós temos dois?
Quando você deve usar um e não o outro?
O Ruby possui dois mecanismos de exceção diferentes: Throw / Catch e Raise / Rescue.
Por que nós temos dois?
Quando você deve usar um e não o outro?
Respostas:
Eu acho que http://hasno.info/ruby-gotchas-and-caveats tem uma explicação decente da diferença:
pegar / arremessar não é o mesmo que levantar / resgatar. catch / throw permite que você saia rapidamente dos blocos de volta a um ponto em que uma captura é definida para um símbolo específico;
raiseé muito caro. thrownão é. Pense throwcomo usar gotopara sair de um loop.
raise, fail, rescue, E ensurelidar com erros , também conhecido como exceçõesthrowe catchsão fluxo de controleDiferentemente de outros idiomas, o throw e catch de Ruby não são usados para exceções. Em vez disso, eles fornecem uma maneira de encerrar a execução mais cedo, quando nenhum trabalho adicional é necessário. (Grimm, 2011)
O término de um único nível de fluxo de controle, como um whileloop, pode ser feito com um simples return. É possível encerrar muitos níveis de fluxo de controle, como um loop aninhado throw.
Embora o mecanismo de exceção de aumento e resgate seja ótimo para abandonar a execução quando algo der errado, às vezes é bom poder pular de uma construção profundamente aninhada durante o processamento normal. É aqui que o catch and throw é útil. (Thomas e Hunt, 2001)
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise oferece uma excelente explicação que duvido que possa melhorar. Para resumir, copiando alguns exemplos de código da postagem do blog enquanto eu vou:
raise/ rescuesão os análogos mais próximos da construção throw/ que catchvocê conhece de outras linguagens (ou da raise/ do Python except). Se você encontrou uma condição de erro e a encontrou throwem outro idioma, deve fazê-lo raiseem Ruby.
Ruby throw/ catchpermite interromper a execução e subir na pilha procurando por catch(como raise/ rescuefaz), mas não é realmente destinado a condições de erro. Ele deve ser usado raramente e existe apenas para quando o catchcomportamento "subir a pilha até encontrar um correspondente " faz sentido para um algoritmo que você está escrevendo, mas não faria sentido pensar nele throwcomo correspondente a um erro doença.
Para que o catch and throw é usado no Ruby? oferece algumas sugestões sobre bons usos do throw/ catchconstruct.
As diferenças comportamentais concretas entre eles incluem:
rescue Fooresgatará instâncias de Fooinclusão de subclasses de Foo. catch(foo)só pegará o mesmo objetoFoo . Não apenas você não pode passar catchum nome de classe para capturar instâncias, como também não fará comparações de igualdade. Por exemplo
catch("foo") do
throw "foo"
end
lhe dará um UncaughtThrowError: uncaught throw "foo"(ou um ArgumentErrornas versões do Ruby anteriores à 2.2)
Várias cláusulas de resgate podem ser listadas ...
begin
do_something_error_prone
rescue AParticularKindOfError
# Insert heroism here.
rescue
write_to_error_log
raise
end
enquanto vários catches precisam ser aninhados ...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
endUm bare rescueé equivalente rescue StandardErrore é uma construção idiomática. Um "nu catch", como catch() {throw :foo}, nunca vai pegar nada e não deve ser usado.
gotoem C / C ++ como @docwhat mencionou, Java tem marcado ruptura e continuar . (Python também tem uma proposta rejeitada para isso).