-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy path2.38.scm
executable file
·69 lines (50 loc) · 2.04 KB
/
2.38.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
(load "myhelpers.scm")
;Exercise 2.38
(define fold-right accumulate)
;OR, let's redefine it...
;Note: fold-right IS RECURSIVE!!!
(define (fold-right op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(fold-right op initial (cdr sequence)))))
(fold-right / 1 (list 1 2 3)) ;3/2
;How? Here's how...
;(fr / 1 (list 1 2 3))
;(/ 1 (fr / 1 (list 2 3)))
;(/ 1 (/ 2 (fr / 1 (list 3))))
;(/ 1 (/ 2 (/ 3 (fr / 1 (list)))))
(/ 1 (/ 2 (/ 3 1)))
;(/ 1 (/ 2 3))
;(/ 1 2/3)
;3/2
;fold-left is ITERATIVE!
(define (fold-left op initial sequence)
(define (iter result rest)
(if (null? rest)
result
(iter (op result (car rest))
(cdr rest))))
(iter initial sequence))
(fold-left / 1 (list 1 2 3)) ;1/6
;"Huh?" you ask? Here's how:
;(fl / 1 (list 1 2 3))
;(iter 1 (list 1 2 3))
;(iter (/ 1 1) (list 2 3))
;(iter (/ 1 2) (list 3))
;(iter (/ 1/2 3) '())
;(iter 1/6 '())
;1/6
;NOTE: Fold-left is iterative, fold right is recursive. That means that if you want to operate left to right (fold left) you're better off using iterative processes. When going from right to left (accumulate or fold right), you should use recursion. This is because you need to cdr down the entire list before you can apply the operations... You're defering the work until the last element is chosen (eg. the right most element of a list). With fold left, you can easily use an iterative process because you're doing calculations with the left most element of a flat list. No need to defer operations because knowing what is the last element isn't important.
(d (fold-right list nil (list 1 2 3)))
(d (fold-left list nil (list 1 2 3)))
;Common operations
(define oper +)
(assert (fold-right oper 0 (list 1 2 3 4)) (fold-left oper 0 (list 1 2 3 4)))
(define oper *)
(assert (fold-right oper 1 (list 1 2 3 4)) (fold-left oper 1 (list 1 2 3 4)))
;Basically, any communitative operations will do.
;Union of sets, Scalar vector or matrix multiplication should also work.
; (op A B) must equal (op B A)
; Good: A*B == B*A
; Bad: A/B != B/A