루비에서 예외 발생과 예외 발생의 차이점은 무엇입니까?


168

루비에는 Throw / Catch와 Raise / Rescue라는 두 가지 예외 메커니즘이 있습니다.

왜 우리는 두 개가 있습니까?

언제 다른 것을 사용하지 말아야합니까?


많은 중첩 언어에서 "네스트 된 루프에서 벗어나기"는 일반적인 요구 사항입니다. @docwhat에서 언급했듯이 C / C ++goto 에서 in 외에도 , Java는 break라고 레이블을 붙였다 . (Python도 이에 대한 제안거부 했습니다.)
Franklin Yu

답변:


104

http://hasno.info/ruby-gotchas-and-caveats 는 그 차이점에 대한 적절한 설명이 있다고 생각 합니다.

캐치 / 투척은 레이즈 / 레스큐와 다릅니다. catch / throw를 사용하면 특정 기호에 대해 catch가 정의 된 지점으로 블록을 신속하게 종료 할 수 있습니다. 구조 상승은 Exception 객체와 관련된 실제 예외 처리 작업입니다.


1
궁금한 점이 있습니다 ... iPad에서 이것을 읽었으므로 1.9에서 테스트 할 수는 없지만 최근 루비 버전에서는 더 이상 유효하지 않습니다.
Denis de Bernardy

12
또한 알 가치가 있습니다 : raise매우 비쌉니다. throw아니다. 루프에서 벗어나기 위해 throw사용 goto하는 것으로 생각하십시오 .
docwhat

4
@Denis 어떤 문제를 언급하고 있습니까?
docwhat

1
연결이 끊어졌습니다!
morhook

성능 차이에 대한 자세한 내용은 루비 캐치 던지기 및 효율성 을 참조하십시오 .
Franklin Yu

110
  • raise, fail, rescue, 및 ensure핸들 오류 라고도 예외
  • throw하고 catch있는 제어 흐름

다른 언어와 달리 Ruby의 throw and catch는 예외에 사용되지 않습니다. 대신 추가 작업이 필요하지 않을 때 실행을 조기에 종료 할 수있는 방법을 제공합니다. (2011 년 그림)

while루프 처럼 단일 레벨의 제어 흐름을 종료하는 것은 간단한 방법으로 수행 할 수 있습니다 return. 중첩 루프와 같이 여러 수준의 제어 흐름을 종료하면을 (를) 수행 할 수 있습니다 throw.

발생 및 구조의 예외 메커니즘은 문제가 발생했을 때 실행을 포기하는 데 유용하지만 정상적인 처리 중에 깊게 중첩 된 구성에서 벗어날 수있는 것이 좋습니다. 여기에 잡기와 던지기가 편리합니다. <토마스 앤 헌트> (2001)

참고 문헌

  1. 그림, 아브디. "던지기, 잡아라, 일어나기, 구출 ... 난 너무 혼란스러워!" RubyLearning 블로그. Np, 2011 년 7 월 11 일. 웹. 2012 년 1 월 1 일. http://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/ .
  2. 토마스, 데이브, 앤드류 헌트 "루비 프로그래밍" : 실용 프로그래머 가이드. Np, 2001. 웹. 2015 년 9 월 29 일. http://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html .

2
Avdi는 팟 캐스트에서 들리는 것처럼 보이지 않습니다 .
hrdwdmrbl

2
루비 학습 링크가 작동하지 않는 것 같습니다. 차이점을 설명하는 또 다른 블로그 게시물이 있습니다. danielchangnyc.github.io/blog/2013/10/23/throw-raise
Dennis

재미 있고 rubylearning.com은 Avdi의 기사 가 여전히 존재 한다고 생각합니다 . 그것이 우리가 물건을 SO에 복사하는 이유입니다. 그래서 손실되지 않습니다!
Jared Beck

21

https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise 는 내가 향상시킬 수없는 의심스러운 훌륭한 설명을 제공합니다. 요약하면 블로그 게시물에서 일부 코드 샘플을 닉킹합니다.

  1. raise/ rescue는 다른 언어 (또는 Python의 / ) 와 친숙한 throw/ catch구문 과 가장 유사한 아날로그 입니다. 오류 상태가 발생하여 다른 언어로 처리 한 경우 Ruby로 해야합니다 .raiseexceptthrowraise

  2. Ruby의 throw/를 catch사용하면 실행을 중단하고 스택 catch과 같이 (처럼 raise/ 처럼 rescue)를 찾을 수 있지만 실제로는 오류 조건을 의미하지는 않습니다. 거의 사용하지 않아야하며, "대응하는 catch동작 을 찾을 때까지 스택을 따라 가십시오 "동작이 작성중인 알고리즘에는 의미가 있지만 throw오류에 해당하는 것으로 생각하는 것은 이치에 맞지 않습니다. 질환.

    Ruby에서 catch와 throw는 무엇입니까? throw/ catch구문 의 훌륭한 사용법에 대한 제안을 제공합니다 .

그들 사이의 구체적인 행동 차이는 다음과 같습니다.

  • rescue FooFoo하위 클래스를 포함하는 인스턴스를 구출합니다 Foo. 같은 객체catch(foo) 만 잡습니다 . 클래스 이름을 전달 하여 인스턴스를 포착 할 수있을뿐만 아니라 동등 비교도 수행하지 않습니다. 예를 들어Foocatch

    catch("foo") do
      throw "foo"
    end
    

    당신에게 줄 것이다 UncaughtThrowError: uncaught throw "foo"(또는 ArgumentError루비의 이전 버전에서 2.2을)

  • 여러 구조 조항을 나열 할 수 있습니다 ...

    begin
      do_something_error_prone
    rescue AParticularKindOfError
      # Insert heroism here.
    rescue
      write_to_error_log
      raise
    end
    

    여러 catches를 중첩해야 하지만 ...

    catch :foo do
      catch :bar do
        do_something_that_can_throw_foo_or_bar
      end
    end
    
  • 베어 (bare) rescuerescue StandardError관용적 구성과 동일 하며 관용적 구성입니다. catch와 같은 "베어 " catch() {throw :foo}는 아무 것도 잡을 수 없으므로 사용해서는 안됩니다.


좋은 설명이지만 의문을 제기합니다. 왜 지구상에서 루비로 디자인하면 다른 언어로 던져 질까요? 그리고 throw도 포함하지만! = 다른 언어로 던져보십시오. 나는 그들의 원래 논리를 볼 수 없습니다
유선 00

@ wired00 (Shrug.) 오늘날 다른 인기있는 언어와 비교했을 때 매우 편심 한 것 같습니다.
Mark Amery

2
@ wired00 : 1960 년대에 구조화 된 오류 처리를 사용한 최초의 실험 이후로 예외를 "건축"이라고하며, 현대적인 예외 처리 방식을 발명 한 주요 기사에서는 예외를 "건물 제기"라고합니다. 리스프와 스몰 토크에서 예외를 "일으킨다"는 루비에게 주요한 영감이되었으며, "프로그래밍"개념 이전에도 개념이 존재했던 하드웨어에서 "예외 발생"또는 "인터럽트 발생" 언어 "가 존재했습니다. 문제는 오히려 다른 언어가 왜 그것을 바꾸었을까요?
Jörg W Mittag

@MarkAmery : "다른 인기있는 언어들"은 루비보다 어리 거나 최소한 현대적 이라는 것을 기억하십시오 . 따라서 다른 언어가 왜 루비와 스몰 토크와 리스프, 하드웨어와 문헌을 따르지 않았는가?
Jörg W Mittag

@ JörgWMittag Interesting-당신은 저에게 약간의 역사적인 연구를하도록 영감을주었습니다. C ++은 루비가 등장하기 몇 년 전부터 예외를 던지는 개념을 가지고 있었고, english.stackexchange.com/a/449209/73974에 따르면이 용어는 실제로 70 년대로 거슬러 올라갑니다. 확립 된 용어를 사용하여 완전히 다른 것을 의미하는 데 사용합니다.
Mark Amery
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.