2011-01-18 2 views
1
jobs.each do | job | 
    msg job.name do 
    break if stop_all_jobs? 
    job.run! 
    end 
end 

def msg(msg, &block) 
    puts 'START ' + msg 
    yield 
    puts 'END ' + msg 
end 

위의 예에서 break은 예상대로 루프를 벗어나지 않습니다. msg 코드 블록에서만 나옵니다.(yield) 블록의 코드에서 루프를 제거하는 방법은 무엇입니까?

다소 이상하게 들릴지 모르겠지만 문맥을 기반으로한다고 생각합니다. yield 코드 블록 내에있는 코드에서 어떻게 루프에서 빠져 나옵니까?

+0

분명히 말하면,''END''가 결코 출력되지 않도록'msg'에서'return'을하고 싶습니까? 아니면 단순히'job.run! '을 호출하지 않고'msg'를 계속 사용 하시겠습니까? – Phrogz

답변

2

한 가지 방법은 throw/catch을 사용하는 것입니다. 아니, 예외가 아니라 Ruby는 오버 헤드없이 예외처럼 작동하는 별도의 흐름 제어 기능을 가지고 있습니다 (비록 내가 어떤 오버 헤드도 없다는 것을 확신 할 수 있지만).

catch :stop_all_jobs do 
    msg job.name do 
    throw :stop_all_jobs if stop_all_jobs? 
    job.run! 
    end 
end 

당신도 catch 블록의 결과 일 것이다 throw 두 번째 인수 값을 전달할 수있다.

잠재적으로 더 읽기 쉬운 솔루션은 코드를 메서드로 압축하고 break 대신 return을 사용하는 것입니다. 그러나 그것은 재미 있지 않을 것입니다.

+0

던지기/잡기가 goto처럼 보입니다. 아니면 나만입니까? – Kris

+0

예. 다른 이름과 반환 값을 갖는 goto입니다. – Theo

+0

Ruby가 throw를 만났을 때 호출 스택을 압축하여 일치하는 심볼이있는 catch 블록을 찾습니다. 발견되면 루비는 스택을 그 지점까지 풀어 블록을 종료합니다. 인용 : http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_exceptions.html – Kris

-2

break 대신 next을 사용하십시오.

관련 문제