如果您要使用不同的值再次进行计算,那么进行第二次计算的唯一原因。在实践中,它是一个 goto,如果你的延续没有被定界,它就是一个无限循环。例如。尝试这个:
(define anotherOnePlus 0)
(let ()
(+ 1 (call/cc (lambda (k) (set! anotherOnePlus k) (k 4)))) ; 5
(anotherOnePlus 4)); 5
您将永远不会得到答案,因为(anotherOnePlus 4)
将您带回到(+ 1 4)
继续(anotherOnePlus 4)
带您再次回来。
功能没有限制。只要它被引用,它就不会被垃圾收集。
一个更好的演示方式call/cc
将是一个更好的例子。如果您要实现map
多个列表,则需要获取cars
除非列表之一为空,否则结果应该为空。您可以通过首先迭代整个列表来确保没有空列表来做到这一点:
(define (cars-1 lsts)
(define (have-elements? lsts)
(cond ((null? lsts) #t)
((null? (car lsts)) #f)
(else (have-elements? (cdr lsts)))))
(define (cars lsts)
(if (null? lsts)
'()
(cons (caar lsts)
(cars (cdr lsts)))))
(if (have-elements? lsts)
(cars lsts)
'()))
但是有一个聪明的解决方案,如果你找到一个你保释的空元素,你就这样做。这可以通过这样的延续来完成:
(define (cars lsts)
(define (cars lsts k)
(cond ((null? lsts) (k '()))
((null? (car lsts)) '())
(else (cars (cdr lsts)
(lambda (res)
(k (cons (caar lsts)
res)))))))
(cars lsts values))
现在,如果我们可以让语言来做延续,而我们只是选择是否使用它们,那不是很好吗?计划为您做到这一点。你这样写:
(define (cars lsts)
(call/cc
(lambda (bail)
(define (cars lsts)
(cond ((null? lsts) '())
((null? (car lsts)) (bail '()))
(else (cons (caar lsts)
(cars (cdr lsts))))))
(cars lsts))))
现在,如果您查看SRFI-1 列表库的参考实现,您会发现他们实际上是这样做的。