Search code examples
schemecontinuationscontinuation-passing

my CPS is right?


in "The Scheme Programming Language 4th Edition", there is a example as below:


(define product
  (lambda (ls)
    (call/cc
      (lambda (break)
        (let f ([ls ls])
          (cond
            [(null? ls) 1]
            [(= (car ls) 0) (break 0)]
            [else (* (car ls) (f (cdr ls)))]))))))
(product '(1 2 3 4 5)) => 120

(product '(7 3 8 0 1 9 5)) => 0

later it is converted into CPS in 3.3 as below


(define product
  (lambda (ls k)
    (let ([break k])
      (let f ([ls ls] [k k])
        (cond
          [(null? ls) (k 1)]
          [(= (car ls) 0) (break 0)]
          [else (f (cdr ls)
                   (lambda (x)
                     (k (* (car ls) x))))])))))
(product '(1 2 3 4 5) (lambda (x) x)) => 120

(product '(7 3 8 0 1 9 5) (lambda (x) x)) => 0

I want to do it myself, The corresponding CPS is below


 (define (product ls prod break)
    (cond
      ((null? ls)
       (break prod))
      ((= (car ls) 0)
       (break 0))
      (else
        (product (cdr ls) (* prod (car ls)) break))))
(product '(1 2 3 4 5) 1 (lambda (x) x)) => 120

(product '(1 2 0 4 5) 1 (lambda (x) x)) => 0

I want to ask my CPS is right? T Thanks in advance!

BEST REGARDS


Solution

  • I think this is the correct implementation :

    (define inside-product #f)  ;; to demonstrate the continuation
    
    (define (product ls prod break)
      (cond
        ((null? ls)
         (begin
           (set! inside-product prod)
           (prod 1)))
        ((= (car ls) 0)
         (break 0))
        (else
         (product (cdr ls) (lambda (x) (prod (* (car ls) x))) break))))
    
    (define identity (lambda (x) x))
    

    The idea of CPS is to keep a track of the recursion.

    > (product (list 1 2 3) identity identity)
    6
    > (inside-product 4)
    24