1

I want to using call/cc to simulating the exception handling statement: try...(throw)...exception. Here's the code:

(define (month n) ; check if it's a month number (1-12)
  (if (or (not (integer? n)) (< n 1) (> n 12))
    (throw -1)
    (display n)
  )
)

(define error (call/cc
   (lambda(throw)
     (begin
       (month 12)
       (month -1)
       (throw -1) ; won't be executed
       (month 10)
       (display "Hello world")
      )
     )
   )
 )

(if error
  (display Error occured!")
)

However, When I executed it, it showed the error (in biwascheme):

Error: execute: unbound symbol: "throw" [(anon), month]

I think that the throw in lambda is not the same as the throw in the called function "month", However, how can I solve it? Is it can be solved with making marco with some keywords? eg:

(define-syntax exception-handling
    (syntax-rules (throw raise error)
      ((_ body catch)
        (define (error
                  (call/cc (lambda (throw) (begin body))))
        )
        (if error (begin catch)))
    )
 )
Tan Kian-teng
  • 81
  • 1
  • 10
  • kudos on the re-formatting -- and most importantly, staying engaged! While writing the code your style of putting the closing parentheses each on its line can make editing easier; but once we have the code, it's customary to put all the closing parentheses on the same line and let the indentation guide us in reading the code. – Will Ness Jul 24 '18 at 21:06

3 Answers3

1

In Scheme, continuations are first-class. A captured continuation is just another value. Pass it in to your month function as another argument:

(define (month n throw) ; check if it's a month number (1-12)
  (if (or (not (integer? n)) (< n 1) (> n 12))
    (throw -1)
    (display n)))

And call it as

     ....
     (month 12 throw)
     ....
     (month 10 throw)
     ....

Your indentation style is not conducive to the readability of your code.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
1

Here is an example of how to use call-with-current-continuation to make a "throw".

#lang r5rs

(define (month n) ; check if it's a month number (1-12)
  (call-with-current-continuation
    (lambda (throw)       
      (define ok (and (integer? n) (<= 1 n 12)))
      (if (not ok)
        (throw "the month number must be between 1 and 12"))
      (display n)
      (newline))))

(month 12)
(month -1)
(month 10)
(display "Hello world\n")
soegaard
  • 30,661
  • 4
  • 57
  • 106
1

I've find the way to simulating try and exception-handling:

(define-syntax try
   (syntax-rules (catch)
     ((_ body catch handling)
        (let ()
          ; evaluating body and save it as an exception.
          (define except (begin body)) 
          (if (and
                (pair? except)
                (eq? (car except) 'exception))
             (handling except)
          )
        )
      )
   )
)

; returns an exception '(exception, "Error messenge")
(define (exception-content msg throw)
  (throw (cons 'exception msg)))
; throw an exception if n = 0
(define (reciprocal n throw)
  (if (= n 0)
     (exception-content "Div 0 error" throw)
     (/ 1 n)
  )
)

; f1(n) = reciprocal(n) + 1
(define (f1 n throw)
  (+ (reciprocal n throw) 1)
)

; main program 
(try ; with call/cc and the continuation variable "throw"
   (call-with-current-continuation
     (lambda (throw)
       (display (f1 2 throw))
       (newline)
       (display (f1 0 throw))

       ; the following won't be executed
       (newline)
       (display (f1 1 throw))
     )
   )

 catch
   ; exception handling
   (lambda (exception)
     (display (cdr exception))
   )
)

The printed result is:

3/2
Div 0 error
Tan Kian-teng
  • 81
  • 1
  • 10
  • of course all this passing around of the `throw` references everywhere shows us, and simulates, the *dynamic* (as in, *not lexical*) nature of exceptions. :) – Will Ness Jul 24 '18 at 21:01