【问题标题】:How to use call/cc for non-local exit in Scheme如何在 Scheme 中使用 call/cc 进行非本地退出
【发布时间】:2014-03-23 05:59:50
【问题描述】:

目前,我正在学习 Scheme 语言。 我对如何使用 call-with-current-continuation 感到困惑。(call/cc) 为了更好地理解它,我为非本地出口编写了一个示例代码。 但它不能正常工作。

有人知道为什么吗?任何帮助,将不胜感激。 提前致谢

[示例代码]

(define (product ls)
  (call/cc
   (lambda (return)
     (cond
      ((null? ls ) =>
       (begin
         (display "list end")
         (newline)
         1)) ;; NG
         ;;(return 1)) ;; OK

      ((not (number? (car ls))) =>
       (begin
         (display "not number")
         (newline)
         (return 0)))
      (else =>
            (begin
              (display (car ls))
              (newline)
              (* (car ls) (product (cdr ls)))))))))

[复制输出]

gosh> (product '(1 2 a 3)) ; it works as I expected.
==> 1
==> 2
==> not number
==> 0 (return)

gosh> (product '(1 2 3)) ;; it doesn't work as I expected. I expect 6 as return value.
==> 1
==> 2
==> 3
==> list end
*** ERROR: invalid application: (1 #t)

【问题讨论】:

    标签: scheme


    【解决方案1】:

    这里发生了几件事。

    首先,您在 cond 子句中插入的 => 似乎导致了问题。在 Scheme 中,=> 有一个特殊的含义……这是你不想要的。把它们拿出来,我想你会看到你的代码表现得如你所愿。

    但是:您对 call/cc 的使用不是实际上会导致非本地退出,正如我相信您所打算的那样。也就是说,我的猜测是您希望零绕过所有等待乘法,但事实并非如此。要看到这一点,请将 0 更改为无法相乘的值——比如字符串"not a number"——然后观察它是否失败。

    这是因为您在每次调用该函数时都重新绑定 return。我想你可能真的想要这样的东西:

    (define (product ls)
      (call/cc
       (lambda (return)
         (letrec ([loop
                  (lambda (ls)
                    (cond
                      ((null? ls )
                       (begin
                         (display "list end")
                         (newline)
                         1)) ;; NG
                      ;;(return 1)) ;; OK
    
                      ((not (number? (car ls)))
                       (begin
                         (display "not number")
                         (newline)
                         (return "not a number")))
                      (else 
                       (begin
                         (display (car ls))
                         (newline)
                         (* (car ls) (loop (cdr ls)))))))])
           (loop ls)))))
    
    (product '(1 2 a 3))
    

    ...产生这个输出:

    1
    2
    not number
    "not a number"
    >
    

    【讨论】:

    • 感谢您的建议。我根据您的评论更改了我的代码。最后,我意识到我的示例代码中存在缺陷。这是对“cond”语法和递归过程中 call/cc 的使用的误解。
    猜你喜欢
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 2013-04-09
    • 2011-07-15
    • 2015-03-27
    • 2014-09-03
    • 2017-11-14
    相关资源
    最近更新 更多