2013-05-11 44 views
7

Tôi đang cố gắng triển khai khối try-catch trong lược đồ bằng cách sử dụng phương thức (call-cc) nhưng tôi không biết cách sử dụng nó như thế nào. Tôi không thể tìm thấy bất kỳ ví dụ nào.Làm cách nào để triển khai khối try-catch trong lược đồ?

Và các ví dụ được tìm thấy chỉ xử lý lỗi nhưng điều tôi muốn làm là: nếu xảy ra lỗi, chương trình lược đồ phải gửi thông báo cho người dùng (thông qua hiển thị ví dụ) mà không cần tạm dừng chương trình.

Điều đó có khả thi không?

Trả lời

6

Vì bạn muốn bắt tất cả các lỗi, chẳng hạn như những người nêu ra bởi cả hai raiseraise-continuable bạn cần cả một xử lý ngoại lệ (để xử lý các điều kiện được nâng lên) và tiếp tục thoát (để tránh tiếp tục với try phần thân). cú pháp đơn giản cho try sẽ là:

(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))))))) 

này được sử dụng như, ví dụ:

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

Lưu ý: đây là R6RS (và R7RS) Đề án.

+0

cảm ơn bạn đã trả lời! đó là những gì tôi đang tìm kiếm nhưng 'với ngoại lệ-xử lý không thể được tìm thấy. Cũng trong vợt và trong r6rs. – Asqan

+0

Vâng, tôi chạy mã trong Ikarus ... 'với ngoại lệ-handler' được tìm thấy trong thư viện (ngoại lệ rnrs). Xem câu trả lời được cập nhật. Xem phần 7.1, trang 24 hoặc tài liệu R6RS-Lib. – GoZoner

+0

Cảm ơn! Ở đây (http://docs.racket-lang.org/r6rs/) là cách bạn sử dụng (rnrs exceptions) trong Racket. – GoZoner

11

Thông thường bạn sẽ sử dụng biểu mẫu with-handlers. Điều này cho phép bạn hiển thị thông báo lỗi hoặc thực hiện bất kỳ hành động nào khác trước khi trả lại giá trị.

#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 

Nếu bạn thực sự muốn sử dụng một sự tiếp nối trực tiếp đối với một số lý do, bạn có thể sử dụng call/ec cho một lỗi/thoát tiếp tục thay vì chung call/cc.

Documents:

+0

try-catch là tính toàn diện dễ hiểu hơn Nhưng cách xử lý ngoại lệ này có vẻ tiện dụng hơn; và tôi sẽ sử dụng điều này tôi nghĩ :) cảm ơn bạn đã trả lời! – Asqan

+3

Bạn có thể dễ dàng viết macro sử dụng 'với handler' nhưng trông giống như try-catch:' (xác định cú pháp thử (cú pháp-quy tắc (bắt) [(_ e (catch [pred handle] ...)) (with-handlers ([xử lý trước] ...) e)])) ' –