Ruby tiene dos mecanismos de excepción diferentes: Lanzar / Atrapar y Elevar / Rescatar.
¿Por qué tenemos dos?
¿Cuándo deberías usar uno y no el otro?
Ruby tiene dos mecanismos de excepción diferentes: Lanzar / Atrapar y Elevar / Rescatar.
¿Por qué tenemos dos?
¿Cuándo deberías usar uno y no el otro?
Respuestas:
Creo que http://hasno.info/ruby-gotchas-and-caveats tiene una explicación decente de la diferencia:
atrapar / lanzar no es lo mismo que elevar / rescatar. catch / throw le permite salir rápidamente de los bloques de regreso a un punto donde se define un catch para un símbolo específico, elevar el rescate es la verdadera excepción que maneja cosas que involucran el objeto Exception.
raisees muy caro. throwno es. Piense throwcomo usar gotopara salir de un bucle.
raise, fail, rescue, Y ensuremango errores , también conocidas como excepcionesthrowy catchson control de flujoA diferencia de otros idiomas, el lanzamiento y la captura de Ruby no se usan para excepciones. En cambio, proporcionan una forma de terminar la ejecución antes de tiempo cuando no se necesita más trabajo. (Grimm, 2011)
Terminar un solo nivel de flujo de control, como un whilebucle, se puede hacer con un simple return. Se puede terminar con muchos niveles de flujo de control, como un bucle anidado throw.
Si bien el mecanismo de excepción de elevar y rescatar es excelente para abandonar la ejecución cuando las cosas salen mal, a veces es bueno poder saltar de una construcción profundamente anidada durante el procesamiento normal. Aquí es donde atrapar y lanzar son útiles. (Thomas y Hunt, 2001)
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise ofrece una excelente explicación que dudo que pueda mejorar. Para resumir, cortando algunos ejemplos de código de la publicación del blog a medida que avanzo:
raise/ rescueson los análogos más cercanos a throw/catch construcción con la que está familiarizado desde otros idiomas (o al raise/ de Python except). Si ha encontrado una condición de error y la superaría throwen otro idioma, debería hacerlo raiseen Ruby.
Ruby throw/catch te permite interrumpir la ejecución y subir la pila buscando un catch(como raise/ rescuedoes), pero en realidad no está destinado a condiciones de error. Debería usarse raramente, y está ahí solo cuando el catchcomportamiento de "caminar por la pila hasta encontrar el correspondiente " tiene sentido para un algoritmo que está escribiendo, pero no tendría sentido pensar throwque corresponde a un error condición.
¿Para qué se usa el atrapar y lanzar en Ruby?ofrece algunas sugerencias sobre buenos usos de throw/ catchconstruct.
Las diferencias de comportamiento concretas entre ellos incluyen:
rescue Foo rescatará instancias de Foo incluir subclases de Foo. catch(foo)sólo coger el mismo objeto,Foo . No solo no puede pasar catchun nombre de clase para capturar instancias de él, sino que ni siquiera hará comparaciones de igualdad. Por ejemplo
catch("foo") do
throw "foo"
end
le dará un UncaughtThrowError: uncaught throw "foo"(o un ArgumentErroren versiones de Ruby anteriores a 2.2)
Se pueden enumerar múltiples cláusulas de rescate ...
begin
do_something_error_prone
rescue AParticularKindOfError
# Insert heroism here.
rescue
write_to_error_log
raise
end
mientras múltiple catch eses necesitan estar anidados ...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
endUn desnudo rescuees equivalente rescue StandardErrory es una construcción idiomática. Un "desnudo catch", como catch() {throw :foo}, nunca atrapará nada y no debe usarse.
gotoen C / C ++ como @docwhat ha mencionado, Java ha etiquetado romper y continuar . (Python también tiene una propuesta rechazada para esto.)