modulos - ¿Cuál es la diferencia entre elevar excepciones y arrojar excepciones en Ruby?
rescue in ruby (3)
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?
Creo que http://hasno.info/ruby-gotchas-and-caveats tiene una explicación decente de la diferencia:
catch / throw no son lo mismo que raise / rescue. catch / throw le permite salir rápidamente de bloques hasta un punto donde se define un catch para un símbolo específico, raise rescue es la excepción real que maneja cosas que involucran el objeto Exception.
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, copiar algunos ejemplos de código de la publicación del blog a medida que avanzo:
raise/rescueson los análogos más cercanos a la construcciónthrow/catchque estás familiarizado de otros idiomas (o Python''sraise/except). Si ha encontrado una condición de error y lathrowen otro idioma, deberaiseen Ruby.El
throw/catchRuby te permite romper la ejecución y subir la pila buscando unacatch(comoraise/rescue), pero en realidad no está hecha para condiciones de error. Se debe usar con poca frecuencia, y solo existe cuando el comportamiento de "subir la pila hasta encontrar lacatchcorrespondiente" tiene sentido para un algoritmo que está escribiendo, pero no tendría sentido pensar que elthrowcorresponde a una condición de error¿Para qué se utilizan catch and throw en Ruby? ofrece algunas sugerencias sobre buenos usos de la construcción
throw/catch.
Las diferencias de comportamiento concretas entre ellos incluyen:
rescue Foorescatará instancias deFooincluidas las subclases deFoo.catch(foo)solo atrapará el mismo objeto,Foo. No solo no puede pasar un nombre de clase para capturar instancias de él, sino que ni siquiera hará comparaciones de igualdad. Por ejemplocatch("foo") do throw "foo" endle dará un
UncaughtThrowError: uncaught throw "foo"(o unArgumentErroren versiones de Ruby anteriores a 2.2)Se pueden enumerar varias cláusulas de rescate ...
begin do_something_error_prone rescue AParticularKindOfError # Insert heroism here. rescue write_to_error_log raise endmientras que múltiples
catchdeben ser anidadas ...catch :foo do catch :bar do do_something_that_can_throw_foo_or_bar end endUn
rescuesimple equivale arescue StandardErrory es una construcción idiomática. Una "catchdescubierto", comocatch() {throw :foo}, nunca atrapará nada y no debería usarse.
-
raise,fail,rescueyensureerrores de manejo, también conocidos como excepciones -
throwycatchson flujo de control
A 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 anticipadamente cuando no se necesita más trabajo. (Grimm, 2011)
La terminación de un solo nivel de flujo de control, como un ciclo while, se puede hacer con un simple return . La terminación de muchos niveles de flujo de control, como un ciclo anidado, se puede hacer con throw .
Si bien el mecanismo de excepción de rescatar y rescatar es excelente para abandonar la ejecución cuando las cosas van 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)
Referencias
- Grimm, Avdi. "Lanzar, atrapar, levantar, rescatar ... ¡Estoy tan confundido!" Blog de RubyLearning. Np, 11 de julio de 2011. Web. 1 de enero de 2012. http://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/ .
- Thomas, Dave y Andrew Hunt. "Programando a Ruby". : La guía del programador pragmático. Np, 2001. Web. 29 de septiembre de 2015. http://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html .