Clarification on callCC

风格不统一 提交于 2019-12-25 01:14:11

问题


My background is Javascript, Python & a bit of Haskell. Hi I am new to Scheme (1 day old). I want to understand the difference between below 2 code snippets.

(define onePlus (lambda (v) (+ 1 v)))
(onePlus 4) ; 5 

With CallCC

(define anotherOnePlus 0)
(+ 1 (call/cc (lambda (k) (set! anotherOnePlus k) (k 4)))) ; 5
(anotherOnePlus 4); 5

Why anyone want to do the 2nd way to get hold of the function you live in. What am I missing in a bigger picture?

Is there any limitations of Scope for getting hold of functions?

(define temp 0)
(+ 1 (+ 2 (+ 3 (call/cc (lambda (k) (set! temp k) (k 4)))))) ; 10
(temp 5) ; 11

Here it is definitely looks like h => 1 + 2 + 3 + h in JS. What if I want to get hold of on (+ 3 h) that means I need to write it in a separate line?


回答1:


The only reason to do the 2nd if you are going to do the calculations over an over again with just different value. In practise it is a goto and if your continuations weren't delimited it is an infinite loop. eg. Try this:

(define anotherOnePlus 0)
(let ()
  (+ 1 (call/cc (lambda (k) (set! anotherOnePlus k) (k 4)))) ; 5
  (anotherOnePlus 4)); 5

You'll never get an answer since (anotherOnePlus 4) brings you back to (+ 1 4) with the continuation (anotherOnePlus 4) which brings you right back again.

There is no limitation of the function. As long as it is referenced it will not be garbage collected.

A better way to demonstrate call/cc would be with a better example. If you ever going to implement map with more than one list you need to fetch the cars unless one of the list is empty, then the result should be empty. You can do this by first iterating the whole list making sure there are no empty lists:

(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)
      '()))

But there is a clever solution where you just do it an if you find an empty element you bail. This can be done with continuations like this:

(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))

Now wouldn't it be great if we could let the language do the continuations and that we just chose if we used them or not? Scheme does that for you. You write it like this:

(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))))

Now if you look at the reference implementation of SRFI-1 List library you'll see they actually do it this way.



来源:https://stackoverflow.com/questions/59241878/clarification-on-callcc

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!