9

这里有几个问题,关于letcc那个在 The Seasoned Schemer 中使用。

(define (intersect-all sets)
  (letcc hop
    (letrec
      ((A (lambda (sets)
            (cond
              ((null? (car sets)) (hop '())
              ((null? (cdr sets)) (car sets))
              (else
                (intersect (car sets)
                           (A (cdr sets)))))))
       ; definition of intersect removed for brevity
      (cond
        ((null? sets) '())
        (else (A sets))))))
  1. 我想我理解letcc实现了什么,这基本上类似于ruby​​ 中的catchand throw(并且看似 CL),这基本上意味着可以通过调用任何命名的东西来缩短整个代码块letcc。这感觉像是我在这一系列短书中遇到的最不“实用”的东西,它让我觉得使用它有点犹豫,因为我想学习一种好的实用风格。我只是误解letcc,还是它不是真正的函数式编程概念,只是为了提高性能而存在?我可以在一些例程中间然后突然进入代码中的另一个点的整个想法感觉有点不对……就像在 Java 中滥用 try/catch 来进行程序流一样。

  2. letcc我在 OS X 中安装的 guile (1.8.7) 版本中似乎不存在。我应该在 guile 中寻找它的另一个名称吗?

  3. 如果我letcc通过将它与 Java 中的 try/catch 或 ruby​​ 中的 catch/throw 进行比较而产生误解(这不是异常处理,只是为了清楚,对于非 ruby​​ 主义者),它在功能级别上究竟是如何工作的? 它能否以更长、更复杂的方式表达,让我相信它毕竟是功能性的?

4

1 回答 1

12
  1. “功能性”有多种含义,但没有任何通俗的含义以任何方式与延续相矛盾。但是它们可能被滥用来创建难以阅读的代码。它们不是可以“被滥用于程序流”的工具——它们程序流工具。

  2. 帮不了你。我知道 Guile 有半新的续集,但我不知道情况如何。它肯定应该有call-with-current-continuation,通常也是在更友好的名称下call/cc,并且let/cc是一个可以构建的简单宏call/cc

    我可以告诉你,在 Racket 中,有一个内置let/cc函数以及同一系列的其他一些内置函数,此外还有一个包含各种控制运算符的完整库(带有广泛的参考列表。)。

  3. 的简单用法let/cc确实类似于 catch/throw 之类的东西——更具体地说,这种延续通常被称为“转义延续”(或有时“向上”)。这是您在该代码中的一种用途,通常用于实现 anabort或 a return

    但是 Scheme 中的延续是可以在任何地方使用的东西。对于显示这种差异的非常简单的示例,请尝试以下操作:

    (define (foo f) (f 100))
    (let/cc k (+ (foo k) "junk") (more junk))
    
  4. 最后,如果您想了解更多关于延续的信息,您可以查看PLAI的相关部分,还有 Matthew Might 写的更简短的示例概述,您可以看到我写的一些基于 PLAI 的课堂笔记,有一些受后一篇文章启发的例子。

于 2012-06-19T16:49:31.270 回答