2013-05-11 9 views
7

Sto cercando di implementare un blocco try-catch in schema usando il metodo (call-cc) ma non sono sicuro di come possa essere usato per quello. Non ho trovato alcun esempio.Come implementare un blocco try-catch nello schema?

E gli esempi trovati contengono solo la gestione degli errori, ma quello che voglio fare è: se si è verificato un errore, il programma di schema deve dare un messaggio all'utente (tramite display per esempio) senza sospendere il programma.

È possibile?

risposta

6

Dal momento che si desidera catturare tutti gli errori, come quelle sollevate da entrambe raise e raise-continuable avresti bisogno sia di un gestore di eccezioni (per gestire condizioni elevate) e una continuazione di uscita (per evitare di continuare conCorpo). sintassi semplice per try sarebbe:

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

Questo viene utilizzato come, ad esempio:

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

Nota: questo è R6RS (e R7RS) Scheme.

+0

grazie per la risposta! questo è quello che stavo cercando ma 'con-exception-handler non è stato trovato. Anche in racchetta e in r6rs. – Asqan

+0

Bene, ho eseguito il codice in Ikarus ... 'with-exceptions-handler' si trova nella libreria (rnrs exceptions). Vedi risposta aggiornata. Vedere la sezione 7.1, pagina 24 o la documentazione di R6RS-Lib. – GoZoner

+0

Grazie! Qui (http://docs.racket-lang.org/r6rs/) è come si usano (eccezioni rnrs) in Racket. – GoZoner

11

In genere si utilizza il modulo with-handlers. Ciò consente di visualizzare un messaggio di errore o eseguire qualsiasi altra azione prima di restituire un valore.

#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 

Se davvero si vuole utilizzare una continuazione diretta per qualche motivo, è possibile utilizzare call/ec per un errore/fuga prosecuzione invece del generale call/cc.

Documenti:

+0

try-catch è più pulito in quanto comprensibilità Ma questo modo di gestire le eccezioni sembra più pratico; e userò questo penso :) grazie per la risposta! – Asqan

+3

Puoi facilmente scrivere una macro che usa 'with-handlers' ma sembra più try-catch:' (define-syntax try (syntax-rules (catch) [(_ e (cattura [handle pred] ...)) (with-handlers ([handle pred]) ...) e)])) ' –

Problemi correlati