Mosh に例外システムを実装しました
R6RS Standard libraries Chapter 7 Exceptions and conditions に書かれている
- (raise ...)
- (raise-continuable ...)
- (with-exception-handler ...)
- (guard ...)
を実装しました。(コンディションは未実装)
trunk にコミットしてあります。
使用例 1
以前追加した REPL は以下のようなコードで動いています。
(define (repl . x) (define (rec) (display "mosh>") (print (eval (read (current-input-port)) '())) (rec)) (rec)) (repl)
もしもユーザー入力のミスにより eval 内で何らかのエラーが起こった場合、デフォルトの例外ハンドラが exit していました。
つまりエラーが起きたらインタプリタが終了していました。
今回追加した guard を使えばエラーを catch して内容を表示し、また復帰することが出来ます。
try 〜 catch のようなものです。
(define (repl . x) (define (rec) (display "mosh>") (guard (e [e (print e) (rec)]) (print (eval (read (current-input-port)) '()))) (rec)) (rec)) (repl)
使用例2
with-exception-handler は2つの手続きを引数にとります。
第1引数は例外ハンドラ、第2引数は実行する手続きです。
例えば
(with-exception-handler (lambda (e) "error") (lambda () "no-error"))
は第2引数の手続きが正常終了したので "no-error" が返ります
逆に
(with-exception-handler (lambda (e) e) (lambda () (raise "error") 5))
は "error" が返ります。
raise で送出されたエラーオブジェクトがエラーハンドラに渡り、エラーハンドラはそのオブジェクトをそのま返しています。