我的背景是Javascript,Python &一点Haskell。嗨,我是新加入的方案(1天大)。我想了解下面两个代码片段之间的区别。
(define onePlus (lambda (v) (+ 1 v)))
(onePlus 4) ; 5 使用CallCC
(define anotherOnePlus 0)
(+ 1 (call/cc (lambda (k) (set! anotherOnePlus k) (k 4)))) ; 5
(anotherOnePlus 4); 5为什么有人想要做第二种方法来获得你所居住的功能。在更大的图景中,我遗漏了什么?
获取函数的范围有什么限制吗?
(define temp 0)
(+ 1 (+ 2 (+ 3 (call/cc (lambda (k) (set! temp k) (k 4)))))) ; 10
(temp 5) ; 11在这里它看起来绝对像JS中的h => 1 + 2 + 3 + h。如果我想要在(+ 3 h)上获得它,这意味着我需要在单独的行中编写它?
发布于 2019-12-15 22:45:07
如果你要用不同的值一遍又一遍地计算,那么做第二个就是唯一的理由。实际上,它是一个goto,如果你的延续没有被分隔,它就是一个无限循环。例如:试试这个:
(define anotherOnePlus 0)
(let ()
(+ 1 (call/cc (lambda (k) (set! anotherOnePlus k) (k 4)))) ; 5
(anotherOnePlus 4)); 5你永远得不到答案,因为(anotherOnePlus 4)会把你带回带有延续(anotherOnePlus 4)的(+ 1 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))现在,如果我们可以让语言进行延续,并且我们可以选择是否使用它们,那不是很好吗?Scheme为您做到了这一点。你可以这样写它:
(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 List library的参考实现,你会发现他们实际上是这样做的。
https://stackoverflow.com/questions/59241878
复制相似问题