złapanie / rzut to nie to samo, co podbicie / uwolnienie. catch / throw pozwala szybko wyjść z bloków z powrotem do punktu, w którym złapanie jest zdefiniowane dla określonego symbolu, podniesienie ratunku to prawdziwa obsługa wyjątków związana z obiektem Exception.
Ciekawostki ... Czytam to z iPada, więc nie mogę przetestować ich w 1.9, ale niektóre z tych pułapek nie są już aktualne w ostatnich wersjach Ruby, prawda?
Denis de Bernardy
12
Warto też wiedzieć: raisejest bardzo drogi. thrownie jest. Pomyśl o throwużyciu, gotoaby wyjść z pętli.
raise, fail, rescueOraz ensureuchwyt błędy , znany także jako wyjątki
throwi catchsą sterowania przepływem
W przeciwieństwie do innych języków, rzut i złapanie Rubiego nie są używane do wyjątków. Zamiast tego zapewniają sposób na wcześniejsze zakończenie wykonywania, gdy nie są potrzebne żadne dalsze prace. (Grimm, 2011)
Zakończenie pojedynczego poziomu przepływu sterowania, takiego jak whilepętla, można wykonać za pomocą prostego return. Można zakończyć wiele poziomów przepływu sterowania, na przykład pętlę zagnieżdżoną throw.
Chociaż wyjątkowy mechanizm podnoszenia i ratowania świetnie nadaje się do porzucania wykonywania, gdy coś pójdzie nie tak, czasami dobrze jest móc wyskoczyć z jakiejś głęboko zagnieżdżonej konstrukcji podczas normalnego przetwarzania. Tutaj przydaje się łapanie i rzucanie. (Thomas i Hunt, 2001)
raise/ rescuesą najbliższymi odpowiednikami konstrukcji throw/, catchktórą znasz z innych języków (lub raise/ except). Jeśli napotkałeś warunek błędu i chciałbyś throwgo pokonać w innym języku, powinieneś raisew Rubim.
Ruby's throw/ catchpozwala przerwać wykonywanie i wspiąć się na stos w poszukiwaniu catch(jak raise/ rescuerobi), ale tak naprawdę nie jest przeznaczony do warunków błędu. Powinien być używany rzadko i jest używany tylko wtedy, gdy zachowanie „idź po stosie, aż znajdziesz odpowiednie catch” ma sens dla algorytmu, który piszesz, ale nie miałoby sensu myśleć o nim throwjako o błędzie stan: schorzenie.
Konkretne różnice w zachowaniu między nimi obejmują:
rescue Foouratuje przypadki Foowłączania podklas Foo. catch(foo)złapie tylko ten sam obiekt,Foo . Nie tylko nie możesz przekazać catchnazwy klasy, aby złapać jej instancje, ale nawet nie będzie robić porównań równości. Na przykład
catch("foo")do
throw "foo"end
da ci UncaughtThrowError: uncaught throw "foo"(lub an ArgumentErrorw wersjach Rubiego starszych niż 2.2)
Można wymienić wiele klauzul ratunkowych ...
begin
do_something_error_prone
rescueAParticularKindOfError# Insert heroism here.rescue
write_to_error_log
raise
end
podczas gdy wiele catches musi być zagnieżdżonych ...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
endend
Bose rescuejest odpowiednikiem rescue StandardErrori jest konstruktem idiomatycznym. Na przykład „goły catch” catch() {throw :foo}nigdy niczego nie złapie i nie powinien być używany.
Dobre wyjaśnienie, ale nasuwa pytanie, dlaczego u licha mieliby zaprojektować podniesienie w rubin = rzut w innym języku. a następnie uwzględnij także rzut, ale to! = rzut w innych językach. Nie widzę tam ich oryginalnej logiki
wired00
@ wired00 ( wzruszając ramionami ) Zgadzam się, że wydaje się to dość ekscentryczne w porównaniu z innymi popularnymi obecnie językami.
Mark Amery,
2
@ wired00: Od czasu pierwszych eksperymentów z ustrukturyzowaną obsługą błędów w latach sześćdziesiątych nazywano to „zgłaszaniem” wyjątku. Nazywa się to „zgłaszaniem” wyjątku w nowatorskich artykułach, w których wynaleziono nowoczesną formę obsługi wyjątków. „podniesienie” wyjątku w Lisps i Smalltalks, które były jednymi z głównych inspiracji dla Rubiego, i nazywa się to „podniesieniem” wyjątku lub „podniesieniem” przerwania w sprzęcie, gdzie koncepcja istniała jeszcze przed koncepcją „programowania” język ”istniał. Pytanie powinno raczej brzmieć: dlaczego te inne języki to zmieniły?
Jörg W Mittag,
@MarkAmery: Pamiętaj, że wiele z tych „innych popularnych języków” jest młodszych od Rubiego lub przynajmniej współcześnie. Zatem pytanie powinno raczej brzmieć: dlaczego te inne języki nie są zgodne z Rubim (i Smalltalk i Lisp oraz sprzętem i literaturą).
Jörg W Mittag,
@ JörgWMittag Interesujące - zainspirowałeś mnie do przeprowadzenia krótkich badań historycznych. C ++ miał pojęcie o „rzucaniu” wyjątku na wiele lat przed pojawieniem się Rubiego, a według english.stackexchange.com/a/449209/73974 termin ten faktycznie sięga lat 70-tych ... więc myślę, że nadal możemy krytykować Ruby za przyjmowanie ustalonej terminologii i używanie jej do oznaczania czegoś zupełnie innego.
goto
w C / C ++, jak wspomniał @docwhat, Java oznaczyła przerwę i kontynuację . (Python również ma odrzuconą propozycję .)Odpowiedzi:
Myślę, że http://hasno.info/ruby-gotchas-and-caveats ma przyzwoite wyjaśnienie różnicy:
źródło
raise
jest bardzo drogi.throw
nie jest. Pomyśl othrow
użyciu,goto
aby wyjść z pętli.raise
,fail
,rescue
Orazensure
uchwyt błędy , znany także jako wyjątkithrow
icatch
są sterowania przepływemZakończenie pojedynczego poziomu przepływu sterowania, takiego jak
while
pętla, można wykonać za pomocą prostegoreturn
. Można zakończyć wiele poziomów przepływu sterowania, na przykład pętlę zagnieżdżonąthrow
.Bibliografia
źródło
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise oferuje doskonałe wyjaśnienie, w które wątpię, czy mogę to poprawić. Podsumowując, po drodze wykrywam kilka przykładów kodu z posta na blogu:
raise
/rescue
są najbliższymi odpowiednikami konstrukcjithrow
/,catch
którą znasz z innych języków (lubraise
/except
). Jeśli napotkałeś warunek błędu i chciałbyśthrow
go pokonać w innym języku, powinieneśraise
w Rubim.Ruby's
throw
/catch
pozwala przerwać wykonywanie i wspiąć się na stos w poszukiwaniucatch
(jakraise
/rescue
robi), ale tak naprawdę nie jest przeznaczony do warunków błędu. Powinien być używany rzadko i jest używany tylko wtedy, gdy zachowanie „idź po stosie, aż znajdziesz odpowiedniecatch
” ma sens dla algorytmu, który piszesz, ale nie miałoby sensu myśleć o nimthrow
jako o błędzie stan: schorzenie.Do czego służy metoda łapania i rzucania w języku Ruby? oferuje kilka sugestii dotyczących ładnych zastosowań konstrukcji
throw
/catch
.Konkretne różnice w zachowaniu między nimi obejmują:
rescue Foo
uratuje przypadkiFoo
włączania podklasFoo
.catch(foo)
złapie tylko ten sam obiekt,Foo
. Nie tylko nie możesz przekazaćcatch
nazwy klasy, aby złapać jej instancje, ale nawet nie będzie robić porównań równości. Na przykładda ci
UncaughtThrowError: uncaught throw "foo"
(lub anArgumentError
w wersjach Rubiego starszych niż 2.2)Można wymienić wiele klauzul ratunkowych ...
podczas gdy wiele
catch
es musi być zagnieżdżonych ...Bose
rescue
jest odpowiednikiemrescue StandardError
i jest konstruktem idiomatycznym. Na przykład „gołycatch
”catch() {throw :foo}
nigdy niczego nie złapie i nie powinien być używany.źródło