2013-05-11 19 views
7

私は(call-cc)メソッドを使用しているスキームでtry-catchブロックを実装しようとしていますが、それをどのように使用できるかわかりません。私は例を見つけることができませんでした。スキームでtry-catchブロックを実装する方法は?

見つかった例にはエラー処理が含まれていますが、エラーが発生した場合、プログラムを中断せずにユーザーにメッセージを表示する必要があります。

これは可能ですか?

答えて

6

あなたは、このようなraiseraise-continuable両方が提起したものとすべてのエラーをキャッチしたいので、あなたは両方のANを必要とするだろう例外ハンドラ(発生条件を処理するため)と終了継続(try本文)。 tryのための簡単な構文は次のようになります。

(import (rnrs base)   ; define-syntax 
     (rnrs exceptions))  ; get `with-exception-handler` 

(define-syntax try 
    (syntax-rules (catch) 
    ((_ body (catch catcher)) 
    (call-with-current-continuation 
     (lambda (exit) 
     (with-exception-handler 
     (lambda (condition) 
      catcher 
      (exit condition)) 
     (lambda() body))))))) 

これは、例えば、として使用されます:

> (try (begin (display "one\n") 
       (raise 'some-error) 
       (display "two\n")) 
    (catch (display "error\n"))) 
one 
error 
some-error  # the return value. 

注:これはR6RS(およびR7RS)スキームです。

+0

ありがとうございました!それは私が探していたものですが、例外ハンドラが見つからなかったためです。ラケットでもr6rsでも。 – Asqan

+0

さて、私はIkarusでコードを実行しました... 'with-exceptions-handler'は(rnrs例外)ライブラリにあります。更新された回答をご覧ください。セクション7.1、ページ24またはR6RS-Libのマニュアルを参照してください。 – GoZoner

+0

ありがとう!ここ(http://docs.racket-lang.org/r6rs/)は、Racketで(rnrsの例外を)使用する方法です。 – GoZoner

11

通常、with-handlersフォームを使用します。これにより、エラーメッセージを表示したり、値を返す前に他のアクションをとることができます。

#lang racket 

(define (foo x) 
    (with-handlers ([exn:fail? (lambda (exn) 
           (displayln (exn-message exn)) 
           #f)]) 
    (/ 1 x))) 

(foo 1) 
; 1 
(foo 0) 
; "/: division by zero" 
; #f 

あなたが実際にいくつかの理由で直接継続を使用したい場合は、代わりに一般的なcall/ccのエラー/エスケープ継続のためのcall/ecを使用することができます。

ドキュメント:

+0

try-catchはもっとクリーンな理解度ですが、このような例外処理はもっと便利です。私はこれを使うつもりです:)答えに感謝します! – Asqan

+3

'with-handlers'を使うマクロは簡単に書くことができますが、try-catchのようになります。'(define-syntax try(syntax-rules(catch)[(_e(catch [pred handle] ...))) (ハンドラ([predハンドル] ...)e)])) ' –

関連する問題