这里有几个问题,关于The Seasoned Schemer中使用的letcc
。
(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))))))
我想我明白了letcc
取得了什么,这基本上类似于ruby(和看似CL)中的catch
和throw
,这基本上意味着整个块通过调用名为letcc
的任何内容,可以缩短代码。这感觉就像我在这一系列短篇小说中遇到的最少“功能性”的东西,它让我觉得有点犹豫使用它,因为我想要学习一个好的功能风格。我只是误解letcc
,还是它不是一个真正的函数式编程概念而只是为了提高性能?整个想法,我可以在一些例程的中间,然后突然到达代码中的另一个点感觉有点错误...就像滥用Java中的try / catch程序流一样。
letcc
似乎不存在于我在OS X中安装的guile(1.8.7)版本中。是否还有其他名称,我应该在guile中寻找它?< / p>
如果我通过将它与Java中的try / catch进行比较来误解letcc
,或者抓住/抛出ruby(这是不异常处理,只是为了清楚,对于非rubyists),它在功能层面上究竟是如何工作的?是否可以用更长,更复杂的方式表达,这让我觉得它毕竟是有用的?
答案 0 :(得分:11)
“功能”有几个含义,但没有任何流行的含义以任何方式与延续相矛盾。但是他们可以被滥用来创建难以阅读的代码。它们不是可以“滥用程序流程”的工具 - 它们是程序流程工具。
无法帮助你。我知道Guile有一个半新近的延续,但我不知道事情的立场。它应该是call-with-current-continuation
,通常也是call/cc
更友好的名称,而let/cc
是一个可以使用call/cc
构建的简单宏。
我可以告诉你,在Racket中let/cc
内置了others builtins中的same family whole library,另外还有PLAI个各种控制运算符(附有大量参考文献。)。
let/cc
的简单用法确实类似于捕获/抛出的东西 - 更具体地说,这种延续通常被称为“逃避延续”(或有时“向上”)。这是您在该代码中使用的一种用法,通常用于实现abort
或return
。
但Scheme中的延续是可以在任何地方使用的东西。有关显示此差异的非常简单的示例,请尝试以下操作:
(define (foo f) (f 100))
(let/cc k (+ (foo k) "junk") (more junk))
最后,如果你想了解更多关于延续的内容,你可以看到brief by-example overview的相关部分,还有更多的class notes,Matthew Might写的,你可以看到一些{{3}} {3}}我写的是基于PLAI的,其中一些例子受到后一篇文章的启发。