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
/rescue
son los análogos más cercanos a la construcciónthrow
/catch
que estás familiarizado de otros idiomas (o Python''sraise
/except
). Si ha encontrado una condición de error y lathrow
en otro idioma, deberaise
en Ruby.El
throw
/catch
Ruby 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 lacatch
correspondiente" tiene sentido para un algoritmo que está escribiendo, pero no tendría sentido pensar que elthrow
corresponde 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 Foo
rescatará instancias deFoo
incluidas 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" end
le dará un
UncaughtThrowError: uncaught throw "foo"
(o unArgumentError
en 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 end
mientras que múltiples
catch
deben ser anidadas ...catch :foo do catch :bar do do_something_that_can_throw_foo_or_bar end end
Un
rescue
simple equivale arescue StandardError
y es una construcción idiomática. Una "catch
descubierto", comocatch() {throw :foo}
, nunca atrapará nada y no debería usarse.
-
raise
,fail
,rescue
yensure
errores de manejo, también conocidos como excepciones -
throw
ycatch
son 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 .