关于callCC的澄清 [英] Clarification on callCC

查看:121
本文介绍了关于callCC的澄清的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的背景是Javascript,Python&一点Haskell.我是Scheme(1天大)的新手.我想了解下面2个代码段之间的区别.

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 

使用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

在这里,它肯定看起来像JS中的h => 1 + 2 + 3 + h. 如果我想掌握(+ 3 h)怎么办,这意味着我需要在单独的一行中写它?

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?

推荐答案

如果要使用不同的值重新进行一次计算,则是执行第二项的唯一原因.实际上,这是一个转到,如果您的延续未定界,则是一个无限循环.例如.试试这个:

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

您将永远不会得到答案,因为(anotherOnePlus 4)继续使用(anotherOnePlus 4)将您带回到(+ 1 4),从而使您再次回到正题.

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.

一个更好的例子来演示call/cc是一个更好的方法.如果要用多个列表实现map,除非列表之一为空,否则需要获取cars,那么结果应该为空.为此,您可以先遍历整个列表,确保没有空列表:

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

现在,如果我们可以让语言进行延续,而我们只是选择是否使用它们,那不是很好吗? Scheme为您做到了.您是这样写的:

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

现在,如果您查看 SRFI-1列表库的参考实现您会看到他们实际上是这样做的.

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

这篇关于关于callCC的澄清的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆