5

PLTSchemeの「エラー」機能に驚いています。ゼロによる除算がある場合、それ以外の再帰は行われず、呼び出しスタックから出てエラーが発生します。

すべての関数の前に暗黙の継続がありますか?エラーはコールスタックを破棄しますか?誰かがこれについて何か考えを持っていますか?

4

1 に答える 1

6

PLT スキームでは、プロシージャエラーにより、エラー文字列を含む例外exn:failが発生します。すべての定義に「暗黙のキャッチ」はありません。次のサンプルを見てください。

;; test.ss
(define (a d)
  (printf "~a~n" (/ 10 d)))

(a 0) ;; The interpreter will exit here.     
(printf "OK~n")

コマンドラインから上記のスクリプトを実行すると、次のような出力後にインタープリターが存在することがわかります

/: division by zero

 === context ===
/home/user/test.ss:1:0: a

例外がユーザー プログラム内で処理されない場合、デフォルト ハンドラが処理するコア インタープリタまで伝搬されます。つまり、例外を出力して終了します。つまり、インタプリタは「例外が発生し、対処方法がわからないので終了します」と言うだけです。これは、JVM やその他の仮想マシンが例外を処理する方法と大差ありません。

PLT スキームの例外処理メカニズムの詳細については、MzScheme 言語マニュアルのwith-handlersdynamic-windをお読みください。これらを使用して、Java の try-catch-finally ブロックをエミュレートすることもできます。

(define (d a b)
  (try
   (printf "~a~n" (/ a b))
   (catch (lambda (ex)
            (printf "Error: ~a" ex)))
   (finally 
    (if (> b -2) 
      (d a (sub1 b))))))

上記を可能にした構文拡張は次のとおりです。

;; try-catch-finally on top of with-handlers and dynamic-wind.

(define-syntax try
  (syntax-rules (catch finally)
    ((_ try-body ... (catch catch-proc))
     (with-handlers (((lambda (ex) #t)
              (lambda (ex) 
            (catch-proc ex))))
            (begin
              try-body ...)))
    ((_ try-body ... (catch catch-proc) (finally fin-body ...))
     (dynamic-wind
     (lambda () ())

     (lambda ()
       (with-handlers (((lambda (ex) #t)
                (lambda (ex) 
                  (catch-proc ex))))
              (begin
                try-body ...)))

     (lambda () fin-body ...)))
    ((_ try-body ... (finally fin-body ...))
     (dynamic-wind
     (lambda () ())

     (lambda () try-body ...)

     (lambda () fin-body ...)))))
于 2009-10-13T02:57:16.213 に答える