如何使lambda中的函数在lambda体内使用的另一个函数中被调用

How to make the function in a lambda be called in another function used inside the body of lambda

我想用call/cc模拟异常处理语句:try...(throw)...exception。这是代码:

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

但是,当我执行它时,它显示错误(在 biwascheme 中):

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

我认为lambda中的throw与被调用函数中的throw不一样"month",但是如何解决呢?是否可以通过使用一些关键字制作 marco 来解决?例如:

(define-syntax exception-handling
    (syntax-rules (throw raise error)
      ((_ body catch)
        (define (error
                  (call/cc (lambda (throw) (begin body))))
        )
        (if error (begin catch)))
    )
 )

在 Scheme 中,continuations 是 first-class。捕获的延续只是另一个值。将它作为另一个参数传递给您的 month 函数:

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

并将其命名为

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

您的缩进风格不利于代码的可读性。

这里是如何使用 call-with-current-continuation 制作 "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")

我找到了模拟 try 和异常处理的方法:

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

打印结果为:

3/2
Div 0 error