In vielen Programmiersprachen ist es üblich, aus verschachtelten Schleifen herauszukommen. Neben dem gotoin C / C ++, wie @docwhat erwähnt hat, hat Java break and continue gekennzeichnet . (Python hat auch einen abgelehnten Vorschlag dafür.)
Fangen / Werfen ist nicht dasselbe wie Erhöhen / Retten. Mit catch / throw können Sie Blöcke schnell bis zu einem Punkt verlassen, an dem ein Fang für ein bestimmtes Symbol definiert ist. Raise Rescue ist die eigentliche Ausnahmebehandlung für das Exception-Objekt.
Neugierig zu wissen ... Lesen Sie dies von einem iPad, können Sie sie also nicht in Version 1.9 testen, aber einige dieser Fallstricke sind in den neuesten Ruby-Versionen nicht mehr gültig, oder?
Denis de Bernardy
12
Auch wissenswert: raiseist sehr teuer. throwist nicht. Stellen Sie sich vor throw, Sie verwenden goto, um aus einer Schleife herauszukommen.
raise, fail, rescue, Und ensureGriff - Fehler , auch bekannt als Ausnahme
throwund catchsind Kontrollfluss
Im Gegensatz zu anderen Sprachen werden Rubys Wurf und Fang nicht für Ausnahmen verwendet. Stattdessen bieten sie eine Möglichkeit, die Ausführung vorzeitig zu beenden, wenn keine weiteren Arbeiten erforderlich sind. (Grimm, 2011)
Das Beenden einer einzelnen Ebene des Kontrollflusses wie eines whileRegelkreises kann mit einem einfachen Vorgang erfolgen return. Das Beenden vieler Ebenen des Kontrollflusses, wie z. B. einer verschachtelten Schleife, kann durchgeführt werden throw.
Während der Ausnahmemechanismus von Raise and Rescue großartig ist, um die Ausführung abzubrechen, wenn etwas schief geht, ist es manchmal schön, während der normalen Verarbeitung aus einem tief verschachtelten Konstrukt herausspringen zu können. Hier bieten sich Fangen und Werfen an. (Thomas und Hunt, 2001)
raise/ rescuesind die nächsten Analoga zu dem Konstrukt throw/, catchdas Sie aus anderen Sprachen kennen (oder zu Pythons raise/ except). Wenn Sie auf eine Fehlerbedingung gestoßen sind und throwdiese in einer anderen Sprache überschreiben würden , sollten Sie dies raisein Ruby tun.
Rubys throw/ catchkönnen Sie die Ausführung brechen und den Stapel klettern für eine Suche catch(wie raise/ der rescueFall ist), ist aber nicht wirklich für Fehlerbedingungen gemeint. Es sollte selten verwendet werden und ist nur dann vorhanden, wenn das catchVerhalten "Gehen Sie den Stapel hinauf, bis Sie ein entsprechendes Verhalten finden " für einen Algorithmus, den Sie schreiben, Sinn macht, aber es wäre nicht sinnvoll, an das zu denkenthrow als einem Fehler entsprechend vorzustellen Bedingung.
Die konkreten Verhaltensunterschiede zwischen ihnen umfassen:
rescue Foowird Instanzen der Aufnahme von FooUnterklassen von retten Foo. catch(foo)fängt nur das gleiche Objekt ,Foo . Sie können nicht nur keinen catchKlassennamen übergeben, um Instanzen davon abzufangen, sondern auch keine Gleichheitsvergleiche durchführen. Zum Beispiel
catch("foo")do
throw "foo"end
gibt Ihnen eine UncaughtThrowError: uncaught throw "foo"(oder eine ArgumentErrorin Versionen von Ruby vor 2.2)
Es können mehrere Rettungsklauseln aufgeführt werden ...
begin
do_something_error_prone
rescueAParticularKindOfError# Insert heroism here.rescue
write_to_error_log
raise
end
während mehrere catches verschachtelt werden müssen ...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
endend
Ein nacktes rescueist gleichbedeutend mit rescue StandardErrorund ist ein idiomatisches Konstrukt. Ein "nackter catch" catch() {throw :foo}wird niemals etwas fangen und sollte nicht verwendet werden.
Gute Erklärung, wirft aber die Frage auf, warum um alles in der Welt sie in Rubin erheben = in einer anderen Sprache werfen würden. und dann auch werfen werfen, aber es! = werfen in anderen Sprachen. Ich kann ihre ursprüngliche Logik dort nicht sehen
wired00
@ wired00 (Achselzucken) Ich stimme zu, dass es im Vergleich zu anderen populären Sprachen heute ziemlich exzentrisch erscheint.
Mark Amery
2
@ wired00: Es wurde seit den ersten Experimenten mit strukturierter Fehlerbehandlung in den 1960er Jahren als "Auslösen" einer Ausnahme bezeichnet. In den wegweisenden Artikeln, die die moderne Form der Ausnahmebehandlung erfanden, wird es als "Auslösen" einer Ausnahme bezeichnet "Auslösen" einer Ausnahme in Lisps und Smalltalks, die einige der Hauptinspirationen für Ruby waren, und es wird "Auslösen" einer Ausnahme oder "Auslösen" eines Interrupts in der Hardware genannt, bei dem das Konzept bereits vor dem Konzept einer "Programmierung" existierte Sprache "existierte. Die Frage sollte eher lauten: Warum haben diese anderen Sprachen das geändert?
Jörg W Mittag
@ MarkAmery: Denken Sie daran, dass viele dieser "anderen populären Sprachen" jünger als Ruby oder zumindest zeitgemäß sind. Die Frage sollte also eher lauten: Warum folgten diese anderen Sprachen nicht Ruby (und Smalltalk und Lisp sowie Hardware und Literatur)?
Jörg W Mittag
@ JörgWMittag Interessant - Sie haben mich zu ein wenig historischer Forschung inspiriert. C ++ hatte den Gedanken, Jahre vor Ruby eine Ausnahme zu "werfen", und laut english.stackexchange.com/a/449209/73974 geht der Begriff tatsächlich auf die 70er Jahre zurück ... also denke ich, dass wir Ruby immer noch kritisieren können etablierte Terminologie nehmen und damit etwas ganz anderes bedeuten.
goto
in C / C ++, wie @docwhat erwähnt hat, hat Java break and continue gekennzeichnet . (Python hat auch einen abgelehnten Vorschlag dafür.)Antworten:
Ich denke, http://hasno.info/ruby-gotchas-and-caveats hat eine anständige Erklärung für den Unterschied:
quelle
raise
ist sehr teuer.throw
ist nicht. Stellen Sie sich vorthrow
, Sie verwendengoto
, um aus einer Schleife herauszukommen.raise
,fail
,rescue
, Undensure
Griff - Fehler , auch bekannt als Ausnahmethrow
undcatch
sind KontrollflussDas Beenden einer einzelnen Ebene des Kontrollflusses wie eines
while
Regelkreises kann mit einem einfachen Vorgang erfolgenreturn
. Das Beenden vieler Ebenen des Kontrollflusses, wie z. B. einer verschachtelten Schleife, kann durchgeführt werdenthrow
.Verweise
quelle
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise bietet eine hervorragende Erklärung, die ich nicht verbessern kann. Zusammenfassend lässt sich sagen, dass ich einige Codebeispiele aus dem Blog-Beitrag geklaut habe:
raise
/rescue
sind die nächsten Analoga zu dem Konstruktthrow
/,catch
das Sie aus anderen Sprachen kennen (oder zu Pythonsraise
/except
). Wenn Sie auf eine Fehlerbedingung gestoßen sind undthrow
diese in einer anderen Sprache überschreiben würden , sollten Sie diesraise
in Ruby tun.Rubys
throw
/catch
können Sie die Ausführung brechen und den Stapel klettern für eine Suchecatch
(wieraise
/ derrescue
Fall ist), ist aber nicht wirklich für Fehlerbedingungen gemeint. Es sollte selten verwendet werden und ist nur dann vorhanden, wenn dascatch
Verhalten "Gehen Sie den Stapel hinauf, bis Sie ein entsprechendes Verhalten finden " für einen Algorithmus, den Sie schreiben, Sinn macht, aber es wäre nicht sinnvoll, an das zu denkenthrow
als einem Fehler entsprechend vorzustellen Bedingung.Wofür wird in Ruby Fangen und Werfen verwendet? bietet einige Vorschläge für nette Verwendungen des
throw
/catch
-Konstrukts.Die konkreten Verhaltensunterschiede zwischen ihnen umfassen:
rescue Foo
wird Instanzen der Aufnahme vonFoo
Unterklassen von rettenFoo
.catch(foo)
fängt nur das gleiche Objekt ,Foo
. Sie können nicht nur keinencatch
Klassennamen übergeben, um Instanzen davon abzufangen, sondern auch keine Gleichheitsvergleiche durchführen. Zum Beispielgibt Ihnen eine
UncaughtThrowError: uncaught throw "foo"
(oder eineArgumentError
in Versionen von Ruby vor 2.2)Es können mehrere Rettungsklauseln aufgeführt werden ...
während mehrere
catch
es verschachtelt werden müssen ...Ein nacktes
rescue
ist gleichbedeutend mitrescue StandardError
und ist ein idiomatisches Konstrukt. Ein "nacktercatch
"catch() {throw :foo}
wird niemals etwas fangen und sollte nicht verwendet werden.quelle