rescueは継続?
2chのRubyについて Part 27の135,136,154に対する意見
もう、2週間も前の事に意見するのもあれだけど、自分の頭の中を整理するのもかねて書きます。(※僕は135本人じゃないです。)
たぶん、136、154は「継続=call/cc」と考えているからここで書き込まれている結論に行き着いたんだと思う。その前の129の発言を考えるとどう考えても「継続=call/cc」なんだけどね。135はちがってもっと広く「継続=現在の計算の次の計算」としてとらえていると思う。
継続は現在の計算の次にやることであって、callccだけが継続では無く、継続渡しで渡している無名関数も継続に当てはまる。「プログラミング言語SCHEME」の例題の翻訳だけど、たとえば、このコードのsuccess、failureはそれぞれ成功、失敗時の継続にあたる。
def integer_divide(x,y,success,failure) if y == 0 failure.call("divide by zero") else success.call(*x.divmod(y)) end end integer_divide(1,1,lambda {|d,m| puts d,m}, lambda {|x| puts x}) # => "1\n0" integer_divide(1,0,lambda {|d,m| puts d,m}, lambda {|x| puts x}) # => "divide by zero"
次にやること(継続)がきちんと実行されてるでしょ。
で、この継続渡しで考えると、rubyのrescueはbeginの中での計算が失敗したときの失敗継続を渡している。'p e'が、失敗時の継続。
begin 1/0 rescue => e p e ensure p "end" end
ってことで、継続渡しも考えるとrescueも継続に含まれる。154の発言は129の発言を考えても軽率だと思う。
僕の意見はこれで終わりです。もし違ってたら教えてください。
あと、
schemeでのrubyっぽいbeginを書いたので貼っとく(やりたかったのはこれ)。
(define ruby-raise #f) (define (div n m) (if (= m 0) (ruby-raise "divide by zero") (/ n m))) (define (ruby-begin expr rescue ensure) (call/cc (lambda (succ) (rescue (call/cc (lambda (raise) (succ (fluid-let ((ruby-raise raise)) (expr)))))))) (ensure)) (ruby-begin (lambda () (div 1 0)) (lambda (e) (display e) (newline)) (lambda () (display "ensure") (newline))) ; => "divide by zero\nensure\n" (ruby-begin (lambda () (div 1 1)) (lambda (e) (display e) (newline)) (lambda () (display "ensure") (newline))) ; => "ensure\n"