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.
raise
es muy caro. throw
no es. Piense throw
como usar goto
para salir de un bucle.
raise
, fail
, rescue
, Y ensure
mango errores , también conocidas como excepcionesthrow
y catch
son 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 while
bucle, 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
/ rescue
son 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 throw
en otro idioma, debería hacerlo raise
en Ruby.
Ruby throw
/catch
te permite interrumpir la ejecución y subir la pila buscando un catch
(como raise
/ rescue
does), pero en realidad no está destinado a condiciones de error. Debería usarse raramente, y está ahí solo cuando el catch
comportamiento de "caminar por la pila hasta encontrar el correspondiente " tiene sentido para un algoritmo que está escribiendo, pero no tendría sentido pensar throw
que corresponde a un error condición.
¿Para qué se usa el atrapar y lanzar en Ruby?ofrece algunas sugerencias sobre buenos usos de throw
/ catch
construct.
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 catch
un 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 ArgumentError
en 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
end
Un desnudo rescue
es equivalente rescue StandardError
y es una construcción idiomática. Un "desnudo catch
", como catch() {throw :foo}
, nunca atrapará nada y no debe usarse.
goto
en C / C ++ como @docwhat ha mencionado, Java ha etiquetado romper y continuar . (Python también tiene una propuesta rechazada para esto.)