2013-05-11 52 views
7

我試圖在使用(call-cc)方法的方案中實現try-catch塊,但我不確定如何使用它。我找不到任何例子。如何在方案中實現try-catch塊?

而發現的例子只包含錯誤處理,但我想做的事是:如果發生錯誤,該方案計劃已經給消息給用戶(通過顯示器,例如)不暫停程序。

這可能嗎?

回答

6

既然你想捕獲所有的錯誤,如雙方raise提出的人與raise-continuable你需要一個都異常處理程序(處理引發的條件)和退出延續(以避免繼續使用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 2013-05-11 03:39:55

+0

嗯,我在Ikarus中運行代碼...在(rnrs exceptions)庫中找到'with-exceptions-handler'。查看更新的答案。請參閱第7.1節,第24頁或R6RS-Lib文檔。 – GoZoner 2013-05-11 03:41:01

+0

謝謝!這裏(http://docs.racket-lang.org/r6rs/)是你如何在球拍中使用(例外)。 – GoZoner 2013-05-11 03:47:32

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/ec的錯誤/逃生延續,而不是一般call/cc

文檔:

+0

try-catch更清晰可理解但這種異常處理方式似乎更方便;我會用這個我想:)謝謝你的答案! – Asqan 2013-05-11 03:45:14

+3

你可以很容易地編寫一個使用'with-handlers'的宏,但看起來更像try-catch:'(define-syntax try(syntax-rules(catch)[(_e(catch [pred handle] ...)) (with-handlers([pred handle] ...)e)]))' – 2013-05-11 14:18:52