简体   繁体   English

函数call / cc的函数参数是否可以等效地调用延续或不调用延续而返回?

[英]Can the function argument to `call/cc` equivalently either invoke the continuation or return without invoking the continuation?

The Scheme Programming Language says 方案编程语言说

Scheme allows the continuation of any expression to be captured with the procedure call/cc . Scheme允许使用过程call/cc捕获任何表达式的延续。 call/cc must be passed a procedure p of one argument. 必须为call/cc传递一个参数为p的过程。 call/cc constructs a concrete representation of the current continuation and passes it to p . call/cc构造当前延续的具体表示并将其传递给p The continuation itself is represented by a procedure k . 连续本身由过程k Each time k is applied to a value, it returns the value to the continuation of the call/cc application. 每次将k应用于值时,它将值返回到call/cc应用程序的继续。 This value becomes, in essence, the value of the application of call/cc . 从本质上讲,该值成为call/cc应用程序的值。 If p returns without invoking k , the value returned by the procedure becomes the value of the application of call/cc . 如果p不调用k而返回,则该过程返回的值将成为call/cc应用程序的值。

Are the two following ways of defining p equivalent, as far as being called by call/cc is concerned: 就用call/cc而言,以下两种定义p等价的方式是:

  • p returns without invoking k , p返回而不调用k
  • p calls k with its otherwise return value? p用其否则返回值调用k

I am not sure how call/cc is defined. 我不确定如何定义call/cc Does call/cc ever directly call the continuation k , besides indirectly via p calling k ? 请问call/cc曾经直接调用延续k ,除了通过间接p调用k

Is it perfectly fine that both call/cc and p don't invoke continuation k ? call/ccp都不调用延续k很好吗?

Yes, (call/cc (lambda (k) 1)) <=> (call/cc (lambda (k) (k 1))) . 是, (call/cc (lambda (k) 1)) <=> (call/cc (lambda (k) (k 1))) You can prove this by using the continuation passing style transform. 您可以通过使用延续传递样式转换来证明这一点。

The key part is the CPS form of call/cc is (lambda (k) (lambda (f) ((fk) k))) . 关键部分是call/cc的CPS形式为(lambda (k) (lambda (f) ((fk) k))) And the CPS forms of the two functions are (lambda (c) (lambda (k) (c 1))) and (lambda (c) (lambda (k) (k 1))) . 这两个函数的CPS形式为(lambda (c) (lambda (k) (c 1)))(lambda (c) (lambda (k) (k 1))) Substitute and simplify and both result in (lambda (k) (k 1)) . 代入和简化,两者都导致(lambda (k) (k 1))

I greatly prefer delimited continuations as they have: 我非常喜欢定界延续,因为它们具有:

(reset (1 + (shift (lambda (f) f)))) <=> (lambda (v) (+ 1 v))

This can also be proved algebraically. 这也可以通过代数证明。

To work out the details of the follow up question we can use the code scheme-cps-convert.rkt from http://matt.might.net/articles/cps-conversion/ 要解决后续问题的详细信息,我们可以使用来自http://matt.might.net/articles/cps-conversion/的代码scheme-cps-convert.rkt

> (T-c '(call/cc (λ (k) 1)) 'halt)
'((λ (f cc) (f (λ (x _) (cc x)) cc)) (λ (k $k2873) ($k2873 1)) halt)
> (T-c '(call/cc (λ (k) (k 1))) 'halt)
'((λ (f cc) (f (λ (x _) (cc x)) cc)) (λ (k $k2940) (k 1 $k2940)) halt)

reducing the first expression: 简化第一个表达式:

  ((λ (f cc) (f (λ (x _) (cc x)) cc)) (λ (k $k2873) ($k2873 1)) halt)
= ((λ (k $k2873) ($k2873 1)) (λ (x _) (halt x)) halt)
= (halt 1)

and the second 第二个

  ((λ (f cc) (f (λ (x _) (cc x)) cc)) (λ (k $k2940) (k 1 $k2940)) halt)
= ((λ (k $k2940) (k 1 $k2940)) (λ (x _) (halt x)) halt)
= ((λ (x _) (halt x)) 1 halt)
= (halt 1)

proves they are equal, so using k or not using k in that position makes no difference. 证明它们相等,因此在该位置使用k或不使用k都没有区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM