这个问题有两种意义:一种无趣和一种有趣:
无趣的。 有没有可以用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 和 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 并没有停止good 特殊用途的黑客攻击:您还可以利用它构建所有曾经破坏编程语言的可怕恐怖。 call/cc 就像接触了一位上古之神:如果你想要恐惧力量真的很方便,但你打电话时最好小心它带来的东西,因为它很可能是超越时空的无法形容的恐怖。