エラーを通知する


Tags: R6RS, コンディション, 例外処理

エラーを通知する手続きには error, assertion-violation, syntax-violation のみっつがある。 error は何らかのエラーが発生したことを表し、 assertion-violation は手続きに不正な引数が渡されたことを表す。 syntax-violation はマクロ展開時に不正な構文が検知されたことを表す。

簡単な引数のチェックやデバッグには構文の assert を使うことができる。これは標準 C ライブラリの assert に相当する。ただし標準 C ライブラリの NDEBUG に相当する機能は R6RS では用意されていない。 assert は構文として定義されてい、処理系は通常の手続きでは実現できないような詳細なエラー報告をすることが期待されている。

これらの手続き・構文で送出されるコンディションはそれぞれ次のような合成コンディションである。

error

&who + &message + &irritants + &error

assertion-violation

&who + &message + &irritants + &assertion

syntax-violation

&who + &message + &syntax

assert

&assertion + &message

ただし、いずれの手続きも who 引数に #f を渡した場合は &who コンディションを含まない。

(import (rnrs))

(define *init-file* "/usr/home/schemer/init.rc")

;; 初期化ファイルがない場合エラーを通知する
(unless (file-exists? *init-file*)
  (error 'load-init-file "Initialization file does not exist." *init-file*))
(import (rnrs))

;; 実数の平方根を求める
(define (real-sqrt x)
  (unless (and (real? x) (>= x 0))
    (assertion-violation 'real-sqrt "non-negative real number required" x))
  (sqrt x))
(import (rnrs))

(define-syntax identifier-append
  (lambda (x)
    (syntax-case x ()
      ((k i is ...)
       (for-all identifier? #'(i is ...))
       (datum->syntax #'k
                      (string->symbol
                       (apply string-append
                              (map (lambda (i)
                                     (symbol->string (syntax->datum i)))
                                   #'(i is ...))))))
      ((_ . xs)
       (syntax-violation 'identifier-append
                         "each argument must be an identifier"
                         x #'xs)))))

#|
(display (identifier-append a ppend)) ; -> #<procedure append>
(display (identifier-append "a" ppend)) ; => &syntax
|#
(import (rnrs))

(define *counter* 0)
(define (inc! n)
  (assert (and (integer? n) (exact? n)))
  (set! *counter* (+ *counter* n)))

(inc! 1)
(inc! "hello") ; エラーが通知される。メッセージの内容は実装依存となる。