SRFI-34はプログラムのための例外ハンドリングです。具体的には
with-exception-handler
、guard
とraise
です。使い方はSRFIに山ほどあるのと、R6RS以降のSchemeでは標準になっているので、このSRFIと標準との定義の違いをあげます。
(call-with-current-continuation (lambda (k) (with-exception-handler (lambda (x) (display "something went wrong") (newline) 'dont-care) (lambda () (+ 1 (raise 'an-error))))))上記の動作はR6RSではエラーとして定義されていますが、このSRFIでは未定義です。これは例外が継続可能かどうかという部分に関わってきます。参照:Is the condition continuable?
SRFIの紹介から多少逸脱するのですが、R6RS及びR7RSでは
guard
がelse
を持っていなかった場合にraise-continuable
で例外を伝播させると定義されています。どういったいきさつがあったのかはR6RSのMLを探っていないので分からないのですが、これは以下のような場合に困ることになるかと思います。
(import (rnrs)) (define-condition-type &connection &error make-connection connection-error?) (with-exception-handler ;; maybe you want to return if the condition is ;; warning (lambda (e) (display "condition is &error") (newline)) (lambda () (let retry () ;; if it's connection error, then retry at this point. ;; if other point, it must be a fatal error. (guard (e ((connection-error? e) (display "connection error! retry") (newline) (retry))) ;; assume this is fatal (error 'connection "connection error")))))コーディングバグといえばそれまでなのですが、投げられた例外が継続可能かどうかというのは例外を投げた手続きによって決定されるといのは一見スマートな解決案に見えて実際にはそうでもないという一例になるかと思います*1。
今回はSRFI-34を紹介しました。
*1:
例えば投げられた例外が
&serious
を含む&warning
のようなものだとwarning?
でチェックすると嵌ります。逆に&serious
を含むものでもraise-continuable
で投げられた場合は継続可能になる等。個人的には筋が悪いなぁと思っています。
No comments:
Post a Comment