Как реализовать блок try-catch в схеме?

Я пытаюсь реализовать блок try-catch в схеме с использованием метода (call-cc), но я не уверен, как его можно использовать для этого. Я не мог найти никакого примера.

и найденные примеры содержат только обработку ошибок, но то, что я хочу сделать: если произошла ошибка, программа Схемы должна дать сообщение пользователю (через дисплей, например) без приостановки программы.

Это возможно?

2 ответов


так как вы хотите, чтобы поймать все ошибки, такие как те, которые поднимают 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) схема.


обычно вы используете 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 для продолжения ошибки / escape вместо общего call/cc.

Docs: