把參數藏起來

把acc藏起來看看

(define (sum l acc)
  (if (null? l)
    acc
    (sum (cdr l) (+ acc (car l)))))
  1. delay 要藏的變數
(define (sum1 l)
  (lambda (acc)
    (if (null? l)
      acc
      ((sum2 (cdr l))
        (+ (car l) acc)))))
  1. 把lambda推到if的兩項
(define (sum2 l)
  (if (null? l)
    (lambda (acc) acc)
    (lambda (acc)
      ((sum2 (cdr l))
        (+ (car l) acc)))))
  1. 抽出遞迴的part
(define (sum3 l)
  (if (null? l)
    (lambda (acc) acc)
    (let ((m (sum3 (cdr l))))
      (lambda (acc)
        (m
          (+ (car l) acc))))))
  1. 把運算抽出來,並把delay的變數塞回去
(define (sum4.5 l)
  (if (null? l)
    (lambda (acc) acc)
    (let ((m (sum4 (cdr l)))
          (f (lambda (acc) (+ (car l) acc)))) ;; maybe use -(minus), i could spot out this error
      (lambda (acc)
        (f (m acc))))))   ;; recursive
;; 這邊變成了先遞迴,等回來再做f
;; 當初自己推導是先寫出這個的!! WHYYYYY

(define (sum4 l)
  (if (null? l)
    (lambda (acc) acc)
    (let ((m (sum4 (cdr l)))
          (f (lambda (acc) (+ (car l) acc))))
      (lambda (acc)
        (m (f acc)))))) ;; iterative

番外篇: 左右遞迴

(define (sub4 l)
  (if (null? l)
    (lambda (acc) acc)
    (let ((m (sub4 (cdr l)))
          (f (lambda (acc) (- (car l) acc))))
      (lambda (acc)
        (m (f acc)))))) ;; iterative, foldl

(define (sub5 l)
  (if (null? l)
    (lambda (acc) acc)
    (let ((m (sub5 (cdr l)))
          (f (lambda (acc) (- (car l) acc))))
      (lambda (acc)
        (f (m acc)))))) ;; recursive, foldr 
((sub4 '(2 3 1 4)) 6)
=> 10
2 - 6 = -4
3 - -4 = 7
1 - 7 = -6
4 - -6 = 10

((sub5 '(2 3 1 4)) 6)
=> 2
4 - 6 = -2
1 - -2 = 3
3 - 3 = 0
2 - 0 = 2

藏 continuation

現在用同樣的方式藏continuation

(define (sum-k l k)
  (if (null? l)
    (k 0)
    (sum-k (cdr l)
           (lambda (ret)
            (k (+ (car l) ret))))))
(define (sum-k2 l)
  (if (null? l)
    (lambda (k) (k 0))
    (lambda (k)
      ((sum-k2 (cdr l))
            (lambda (ret)
              (k (+ (car l) ret)))))))
(define (sum-k3 l)
  (if (null? l)
    (lambda (k) (k 0))
    (let ((m (sum-k3 (cdr l))))
      (lambda (k)
        (m
          (lambda (ret)
            (k (+ (car l) ret))))))))
(define (sum-k4 l)
  (if (null? l)
    (lambda (k) (k 0))
    (let ((m (sum-k3 (cdr l)))
          (f (lambda (ret)
                (lambda (k)
                  (k (+ (car l) ret))))))
      (lambda (k)
        ((m f) k))))) ;; NOOOOO!!! f should contains k before m

(define (sum-k4 l)
  (if (null? l)
    (lambda (k) (k 0))
    (let ((m (sum-k4 (cdr l)))
          (f (lambda (ret)
                (lambda (k)
                  (k (+ (car l) ret))))))
      (lambda (k)
        (m (lambda (v) ((f v) k))))))

cont monad

(define (bind m f)
    (lambda (k)
        (m (lambda (v) ((f v) k)))))
(define (return v)
    (lambda (k) (k v)))
(define (sum' l)
  (callcc (lambda (exit)
      (cond
        ((null? l) (return 0))
        (else (bind
                (sum' (cdr l))
                (lambda (ret)
                    (lambda (k)
                        (k (+ ret (car l)))))))))))

callcc

(define (callcc f)
  (λ (k)
    ((f (λ (ret) ;; 要跳出去時,會先收到值
          (λ (_) ;; 原本接下來要做的事
            (k ret)))) ;; 直接用之前的
     k))) ;; 用之前的