把參數藏起來
把acc藏起來看看
(define (sum l acc)
(if (null? l)
acc
(sum (cdr l) (+ acc (car l)))))
- delay 要藏的變數
(define (sum1 l)
(lambda (acc)
(if (null? l)
acc
((sum2 (cdr l))
(+ (car l) acc)))))
- 把lambda推到if的兩項
(define (sum2 l)
(if (null? l)
(lambda (acc) acc)
(lambda (acc)
((sum2 (cdr l))
(+ (car l) acc)))))
- 抽出遞迴的part
(define (sum3 l)
(if (null? l)
(lambda (acc) acc)
(let ((m (sum3 (cdr l))))
(lambda (acc)
(m
(+ (car l) acc))))))
- 把運算抽出來,並把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))) ;; 用之前的