実践Common lispを読み始めた-第19章 例外処理を超えて:コンディションと再起動(2)

再起動

例外が発生したときに、大域脱出せずに処理を継続させるための仕組みといったらいいのかな。

CL-USER> (defun read-eval-print-loop (level)
	   (with-simple-restart
	       (abort "Exit command ~D." level) ;;再起動の定義。ここではread-eval-print-loopを抜ける
	     (loop
		  (with-simple-restart
		      (abort "Return to command ~D." level) ;;別の再起動の定義。発生したエラー処理をスキップして次のREPL処理を実行
		    (let ((form (prog2
				    (fresh-line)
				    (read)
				  (fresh-line))))
		      (prin1 (eval form)))))))
				  
READ-EVAL-PRINT-LOOP
CL-USER> (read-eval-print-loop 1)
(+ 'a 3)  ;;わざとエラーを発生させる

;;デバッガが起動する
`A' is not of the expected type `NUMBER'
   [Condition of type TYPE-ERROR]

Restarts:
  0: [ABORT] Return to command 1.
  1: [ABORT] Exit command 1.
  2: [ABORT-REQUEST] Abort handling SLIME request.
  3: [ABORT] Abort entirely from this (lisp) process.

上記のコードはISBN:4320025881:COMMON LISP 第2版より引用

restart-case

handler-caseみたいな書き方になるが、コンディションの捕捉の替わりに再起動を定義する。

;;
;; sample.lisp
;;
(define-condition runtime-exception (error) 
  ((desc :initarg :message :reader message)
   (value :initarg :value :reader value)))

(defun level3 (arg)
  (error 'runtime-exception :message "RuntimeException" :value arg))

(defun restart-sample (arg)
  (restart-case (level3 10)
    (foo)
    (bar)
    ))

;;
;;REPL
;;
CL-USER> (restart-sample 10)

;;デバッガ
#<RUNTIME-EXCEPTION @ #x106065ba>
   [Condition of type RUNTIME-EXCEPTION]

Restarts:
  0: [FOO] FOO
  1: [BAR] BAR
  2: [ABORT-REQUEST] Abort handling SLIME request.
  3: [ABORT] Abort entirely from this (lisp) process.