(본 게시물은 저작권의 문제 발생시 출판사의 요청에 의해 삭제될 수 있습니다.)
Catch와 Throw
raise와 rescue 메커니즘은 무언가 잘못되었을 때 실행을 멈추는데 효과적이다. 일반적인 실행 중에 여러 겹으로 둘러싸인 코드 밖으로 탈출할 수 있다면 유용할것이다. 이 때 사용하는 문법이 catch throw 이다.
아래의 예제는 한 번에 하나씩 단어 리스트를 읽어와 배열에 추가한다. 전부 읽어오고 나서 배열을 역순으로 출력한다. 처리 과정에서 정상적인 단어를 포함하지 않는 줄을 만나면 모든 과정을 중지한다.
word_list - File.open("wordlist")
catch (:done) do
result = [ ]
while line = word_list.gets
word = line.chomp
throw :done unless word =~ /^\w+$/
result << word
end
puts result.reverse
end
catch는 이름(Symbol, String)이 붙여진 블록을 정의한다. 이 블록은 throw를 만날 때까지 실행된다. throw를 만나면 루비는 해당하는 심벌을 가진 catch를 찾아 코드를 거슬러 올라간다. 그리고 찾게 되면 루비는 해당 위치로 되돌린 뒤 블록을 종료한다.
따라서 위의 예제는 입력된 문자열이 정상적인 형식을 가지지 않았을 경우 throw에 대응하는 catch 블록의 끝으로 이동한다. while을 반복하는 것 뿐만 아니라 거꾸로 리스트를 출력하는 출력도 실행하지 않는다. throw에 두 번째 매개 변수를 넘겨주면 그 값이 catch의 반환값이 된다.
아래의 예제에서는 "wow*."라는 잘못된 줄이 포함되어 있어 블록을 종료한다. throw의 두번 째 매개변수를 생략하면 catch는 nil을 반환한다.
word_list - File.open("wordlist")
word_in_error catch (:done) do
result = [ ]
while line = word_list.gets
word = line.chomp
throw (:done, word) unless word =~ /^\w+$/
puts result.reverse
end
if word_in_error
puts "Failed: '#{word_in_error}' found, but a word was expected"
end
실행결과
Failed: '*wow*' found, but a word was expected
다음 예제는 프롬프트에 !가 입력되었을때 사용자와의 대화를 끝내는 용도로 throw를 사용한다.
def prompt_and_get(prompt)
print prompt
res = readline.chomp
throw :quit_requested if res == "!"
res
end
catch :quit_requested do
name = prompt_and_get("Name: ")
age = prompt_and_get("Age: ")
sex = prompt_and_get("Sex : ")
#
end
위 예제에서 보듯 throw가 꼭 catch 블록과 같은 정적 범위에 있어야 할 필요는 없다.
끄읕