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. throw
não é. Pense throw
como usar goto
para sair de um loop.
raise
, fail
, rescue
, E ensure
lidar com erros , também conhecido como exceçõesthrow
e catch
sã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 while
loop, 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
/ rescue
são os análogos mais próximos da construção throw
/ que catch
você conhece de outras linguagens (ou da raise
/ do Python except
). Se você encontrou uma condição de erro e a encontrou throw
em outro idioma, deve fazê-lo raise
em Ruby.
Ruby throw
/ catch
permite interromper a execução e subir na pilha procurando por catch
(como raise
/ rescue
faz), mas não é realmente destinado a condições de erro. Ele deve ser usado raramente e existe apenas para quando o catch
comportamento "subir a pilha até encontrar um correspondente " faz sentido para um algoritmo que você está escrevendo, mas não faria sentido pensar nele throw
como correspondente a um erro doença.
Para que o catch and throw é usado no Ruby? oferece algumas sugestões sobre bons usos do throw
/ catch
construct.
As diferenças comportamentais concretas entre eles incluem:
rescue Foo
resgatará instâncias de Foo
inclusão de subclasses de Foo
. catch(foo)
só pegará o mesmo objetoFoo
. Não apenas você não pode passar catch
um 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 ArgumentError
nas 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 catch
es precisam ser aninhados ...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
end
Um bare rescue
é equivalente rescue StandardError
e é uma construção idiomática. Um "nu catch
", como catch() {throw :foo}
, nunca vai pegar nada e não deve ser usado.
goto
em C / C ++ como @docwhat mencionou, Java tem marcado ruptura e continuar . (Python também tem uma proposta rejeitada para isso).