这个问题有两种意义:一种无趣和一种有趣:
无趣的那一个。是否有一些你可以用call/cc
没有它的语言做不到的计算?
不,没有:call/cc
不会使语言更强大:众所周知,只有 λ 和函数应用程序的语言等效于通用图灵机,因此没有(已知...)更强大的计算系统。
但从编程语言设计的角度来看,这有点无趣:受内存和 c 的正常限制,几乎所有编程语言都等同于 UTM,但人们仍然更喜欢使用不涉及打孔的语言如果可以的话,用纸胶带。
有趣的一个。是不是这种情况call/cc
使得编程语言的一些理想特性更容易表达?
答案是肯定的,确实如此。我只举几个例子。假设您想在您的语言中使用某种非本地退出功能,因此一些深度嵌套的程序可以说“我想退出这个地狱”,而不必爬回一些很棒的层功能。这是微不足道的call/cc
:继续过程是转义过程。如果你想让它更好,你可以用一些语法包装它:
(define-syntax with-escape
(syntax-rules ()
[(_ (e) form ...)
(call/cc (λ (e) form ...))]))
(with-escape (e)
... code in here, and can call e to escape, and return some values ...)
你可以在没有的情况下实现这个call/cc
吗?嗯,是的,但不是不依赖其他一些特殊结构(比如CL 中的block
and return-from
),或者不以某种方式彻底改变语言。
你可以在这样的基础上实现各种非本地转义。
或者,好吧,假设您想要 GO TO(以下示例是 Racket):
(define (test n)
(define m 0)
(define start (call/cc (λ (c) c)))
(printf "here ~A~%" m)
(set! m (+ m 1))
(when (< m n)
(start start)))
或者,使用一些语法:
(define-syntax-rule (label place)
(define place (call/cc identity)))
(define (go place)
(place place))
(define (horrid n)
(define m 0)
(label start)
(printf "here ~A~%" m)
(set! m (+ m 1))
(when (< m n)
(go start)))
所以,好吧,这可能不是编程语言的理想特性。但是,好吧,Scheme 没有 GO TO 权限,但在这里,它确实有。
所以,是的,call/cc
(尤其是与宏结合使用时)可以表达编程语言的许多理想特性。其他语言有所有这些特殊用途的、有限的 hack,Scheme 有这个通用的东西,所有这些特殊用途的 hack 都可以从中构建。
问题在于,良好call/cc
的特殊用途黑客并不止于此:您还可以构建所有曾经破坏编程语言的可怕恐怖。 就像接触上古之神:想要恐惧之力确实很方便,但召唤的时候要小心它带来的东西,因为它很可能是来自时空之外的无法形容的恐怖。call/cc