• Scheme call/cc 研究


    目前尚不清楚实质,但已经能够从形式上理解它的某些好处,有个很简单的连乘函数可以说明:

    为了展示究竟发生了什么,我包装了下乘法函数,将其变为mul.

    我们将比较product和xproduct的区别.

    ;包装乘法函数
    (define (mul x y) 
      (display x) 
      (display " * ")
      (display y)
      (newline)
      (* x y))
    
    
    ;常规版
    (define (product ls)
      (let f ((ls ls))
        (cond
          ((null? ls) 1)
          ((= (car ls) 0) 0)
          (else (mul (car ls) (f (cdr ls)))))))
    
    ;call/cc版
    (define xproduct
      (lambda (ls)
        (call/cc
         (lambda (break)
           (let f ((ls ls))
             (cond
               ((null? ls) 1)
               ((= (car ls) 0) (break 0))
               (else (mul (car ls) (f (cdr ls))))))))))
    ;比较
    (product '(1 2 3 4 5))
    (xproduct '(1 2 3 4 5))
    (product '(1 2 3 0 5))
    (xproduct '(1 2 3 0 5))

    结果:

    5 * 1
    4 * 5
    3 * 20
    2 * 60
    1 * 120
    120
    5 * 1
    4 * 5
    3 * 20
    2 * 60
    1 * 120
    120
    3 * 0
    2 * 0
    1 * 0
    0
    0

    我们可以看到,对不含0的连乘,两个函数的内部运行是一样的.

    然而对于包含0的连乘,call/cc的方式就显得比较合理.

    product碰到0,即使能够中止递归过程,返回一个0,也仅此而已,它仍然需要笨拙地把这个0和前面已经存在的数进行连乘.

    而人脑认为这是愚蠢的,因为只要发现有一个0,那么无论其他数是怎样的,最终结果必然是0,所以直接返回0就可以了.

    call/cc正是在模拟人脑这一想法.

    下面展示xproduct函数,对于(1 2 3 0)和(1 2 3 4)两种情况,它的函数体分别是怎么展开的:

    > (call/cc (lambda(break)(* 1(* 2(* 3 (break 0))))))
    0
    > (call/cc (lambda(break)(* 1(* 2(* 3 (* 4 1))))))
    24
    (let 
        ((@ (lambda (x) (display "@") x))
         (* (lambda (x) (display "*") x))
         (f (lambda (x) x)))
      ((@ (call/cc f))(* (call/cc f))))
  • 相关阅读:
    EJB到底是什么,真的那么神秘吗??
    An Assembly Language
    Memory Layout (Virtual address space of a C process)
    手机测试用例-游戏测试用例
    手机测试用例-工具箱测试用例
    手机测试用例-输入法测试用例
    手机测试用例-时钟测试用例
    手机测试用例-多媒体测试用例
    手机测试用例-设置测试用例
    手机测试用例-通话记录测试用例
  • 原文地址:https://www.cnblogs.com/xiangnan/p/3436097.html
Copyright © 2020-2023  润新知