next up previous
Next: 8.5 Call/CCによる自動バックトラック Up: 8 Continuation(継続) Previous: 8.3 無限の ExtentをもつContinuation

8.4 Catch としての使い方の例

CommonLispのCatch, Throwを用いる例として,

(defun print-table (l)
  (catch 'not-a-number
    (mapcar #'print-sqrt-abs l)))

(defun print-sqrt-abs (x)
  (print (sqrt (abs (must-be-number x)))))

(defun must-be-number (x)
  (if (numberp x) x
    (throw 'not-a-number "huh?")))

<cl> (print-table '(1 -2 a 10))

1.0 
1.4142135 
"huh?"
というように,数以外のものがきたらそこで中断して catchへ戻ってくるものを作ることができます. これと同じことは,

<cl> (scheme-interpreter)
==> (define (print-table l)
        (call/cc
          (lambda (escape)
            (set! not-a-number escape)
            (map print-sqrt-abs l))))

PRINT-TABLE 

==> (define (print-sqrt-abs x)
        (write (sqrt (abs (must-be-number x))))
        (newline))

PRINT-SQRT-ABS 

==> (define (must-be-number x)
        (if (number? x) x
           (not-a-number "huh?")))

MUST-BE-NUMBER 

==> (define (map fn l)
       (if (null? l)
             nil
          (cons (fn (car l))
             (map fn (cdr l)))))

MAP 

==> (print-table '(1 -2 a 10))
1.0
1.4142135

"huh?" 

==>
というぐあいにcall/ccを用いて作ることができます. つまり,catchしたいところで,call/ccを行い, そこでのcontinuationを大域変数に保存し, そのcall/ccへ戻りたいところで,その大域変数 に保存したcontinuationを実行するという形で 実現が可能です.

generated through LaTeX2HTML. M.Inaba 平成18年5月6日