Sicp

Download as pdf or txt
Download as pdf or txt
You are on page 1of 90
At a glance
Powered by AI
The document discusses concepts from the Structure and Interpretation of Computer Programs (SICP) textbook including procedures, recursion, data abstraction and symbolic processing.

The document covers topics like procedures, recursion, data abstraction, symbolic processing, hierarchical data structures and closure properties.

Data structures like sequences, hierarchical structures and symbolic data are discussed.

Structure and Interpretation of Computer Programs (SICP)

worked examples
Mac Radigan

Abstract
A collection of worked examples from Gerald Sussmans book Structure and Interpretation of Computer Programs (SICP) [1].

Contents
1 Building Abstractions with Procedures
1.1

1.2

1.3

The Elements of Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.1.1

Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.1.2

Naming and the Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.1.3

Evaluating Combinations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.1.4

Compound Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.1.5

The Substitution Model for Procedure Application . . . . . . . . . . . . . . . . . . . .

10

1.1.6

Conditional Expressions and Predicates . . . . . . . . . . . . . . . . . . . . . . . . . .

17

1.1.7

Example: Square Roots by Newtons Method . . . . . . . . . . . . . . . . . . . . . . .

17

1.1.8

Procedures as Black-Box Abstractions . . . . . . . . . . . . . . . . . . . . . . . . . . .

19

Procedures and the Processes They Generate . . . . . . . . . . . . . . . . . . . . . . . . . . .

19

1.2.1

Linear Recursion and Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

19

1.2.2

Tree Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

27

1.2.3

Orders of Growth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

27

1.2.4

Exponentiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

27

1.2.5

Greatest Common Divisors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

1.2.6

Example: Testing for Primality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

Formulating Abstractions with Higher-Order Procedures . . . . . . . . . . . . . . . . . . . . .

32

1.3.1

Procedures as Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

1.3.2

Constructing Procedures Using Lambda . . . . . . . . . . . . . . . . . . . . . . . . . .

32

1.3.3

Procedures as General Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

1.3.4

Procedures as Returned Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

2 Building Abstractions with Data


2.1

2.2

2.3

2.4

2.5

34

Introduction to Data Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

34

2.1.1

Example: Arithmetic Operations for Rational Numbers . . . . . . . . . . . . . . . . .

34

2.1.2

Abstraction Barriers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

36

2.1.3

What Is Meant by Data? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

2.1.4

Extended Exercise: Interval Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . .

39

Hierarchical Data and the Closure Property . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

2.2.1

Representing Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

2.2.2

Hierarchical Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

2.2.3

Sequences as Conventional Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

2.2.4

Example: A Picture Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

Symbolic Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

47

2.3.1

Quotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

47

2.3.2

Example: Symbolic Differentiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

52

2.3.3

Example: Representing Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

2.3.4

Example: Huffman Encoding Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

Multiple Representations for Abstract Data . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

2.4.1

Representations for Complex Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

2.4.2

Tagged data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

2.4.3

Data-Directed Programming and Additivity . . . . . . . . . . . . . . . . . . . . . . . .

55

Systems with Generic Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

2.5.1

Generic Arithmetic Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

2.5.2

Combining Data of Different Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

2.5.3

Example: Symbolic Algebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

3 Modularity, Objects, and State


3.1

56

Assignment and Local State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.1.1

Local State Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.1.2

The Benefits of Introducing Assignment . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.1.3
3.2

3.3

3.4

3.5

The Costs of Introducing Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

The Environment Model of Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.2.1

The Rules for Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.2.2

Applying Simple Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.2.3

Frames as the Repository of Local State . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.2.4

Internal Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

Modeling with Mutable Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.3.1

Mutable List Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.3.2

Representing Queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.3.3

Representing Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.3.4

A Simulator for Digital Circuits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.3.5

Propagation of Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

Concurrency: Time Is of the Essence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.4.1

The Nature of Time in Concurrent Systems . . . . . . . . . . . . . . . . . . . . . . . .

56

3.4.2

Mechanisms for Controlling Concurrency . . . . . . . . . . . . . . . . . . . . . . . . .

56

Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.5.1

Streams Are Delayed Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

3.5.2

Infinite Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

58

3.5.3

Exploiting the Stream Paradigm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

58

3.5.4

Streams and Delayed Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

58

3.5.5

Modularity of Functional Programs and Modularity of Objects . . . . . . . . . . . . .

58

4 Metalinguistic Abstraction
4.1

4.2

59

The Metacircular Evaluator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.1.1

The Core of the Evaluator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.1.2

Representing Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.1.3

Evaluator Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.1.4

Running the Evaluator as a Program . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.1.5

Data as Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.1.6

Internal Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.1.7

Separating Syntactic Analysis from Execution . . . . . . . . . . . . . . . . . . . . . . .

60

Variations on a Scheme Lazy Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.2.1

60

Normal Order and Applicative Order . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.3

4.4

4.2.2

An Interpreter with Lazy Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.2.3

Streams as Lazy Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

Variations on a Scheme Nondeterministic Computing . . . . . . . . . . . . . . . . . . . . . .

60

4.3.1

Amb and Search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.3.2

Examples of Nondeterministic Programs . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.3.3

Implementing the Amb Evaluator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

Logic Programming

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.4.1

Deductive Information Retrieval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

4.4.2

How the Query System Works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

67

4.4.3

Is Logic Programming Mathematical Logic? . . . . . . . . . . . . . . . . . . . . . . . .

67

4.4.4

Implementing the Query System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

67

5 Computing with Register Machines


5.1

5.2

5.3

5.4

5.5

69

Designing Register Machines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.1.1

A Language for Describing Register Machines . . . . . . . . . . . . . . . . . . . . . . .

69

5.1.2

Abstraction in Machine Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.1.3

Subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.1.4

Using a Stack to Implement Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.1.5

Instruction Summary

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

A Register-Machine Simulator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.2.1

The Machine Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.2.2

The Assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.2.3

Generating Execution Procedures for Instructions

. . . . . . . . . . . . . . . . . . . .

69

5.2.4

Monitoring Machine Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

Storage Allocation and Garbage Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.3.1

Memory as Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.3.2

Maintaining the Illusion of Infinite Memory . . . . . . . . . . . . . . . . . . . . . . . .

69

The Explicit-Control Evaluator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.4.1

The Core of the Explicit-Control Evaluator . . . . . . . . . . . . . . . . . . . . . . . .

69

5.4.2

Sequence Evaluation and Tail Recursion . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.4.3

Conditionals, Assignments, and Definitions . . . . . . . . . . . . . . . . . . . . . . . .

69

5.4.4

Running the Evaluator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.5.1

Structure of the Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.5.2

Compiling Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.5.3

Compiling Combinations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.5.4

Combining Instruction Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.5.5

An Example of Compiled Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.5.6

Lexical Addressing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

5.5.7

Interfacing Compiled Code to the Evaluator . . . . . . . . . . . . . . . . . . . . . . . .

69

6 Appendix A: Modules
6.1

70

util.scm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 Appendix B: Installation Notes


7.1

70
78

Chicken Scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8 Appendix C: Notation

78
79

8.1

Membership . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79

8.2

Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79

8.3

Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79

8.4

Equality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

80

8.5

Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

80

9 Appendix D: Y-Combinator

81

9.1

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

81

9.2

Cannonical Expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

81

9.3

Connonical Form in Scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

81

9.3.1

Strict Scheme (Chicken) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

81

9.3.2

Using Lazy Evaluation (Racket #lang lazy) . . . . . . . . . . . . . . . . . . . . . . . .

82

Normal Order Y Combinator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

83

9.4.1

Strict Scheme (Chicken) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

83

9.4.2

Using Strict Evaluation (Racket) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

84

9.4.3

Using Lazy Evaluation (Racket #lang lazy) . . . . . . . . . . . . . . . . . . . . . . . .

84

Strict (Applicative-Order) Y Combinator . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

85

9.5.1

Strict Scheme (Chicken) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

85

9.5.2

Using Strict Evaluation (Racket) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

87

9.5.3

Using Lazy Evaluation (Racket #lang lazy) . . . . . . . . . . . . . . . . . . . . . . . .

88

9.4

9.5

Building Abstractions with Procedures

1.1

The Elements of Programming

1.1.1

Expressions

Exercise 1.1. Below is a sequence of expressions. What is the result printed by the interpreter in response
to each expression? Assume that the sequence is to be evaluated in the order in which it is presented.

#!/usr/bin/csi -s

;; sicp_ch1_e1-1.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 1.1. Below is a sequence of expressions. What is the result printed by the interpreter in

;;; response to each expression? Assume that the sequence is to be evaluated in the order in which it is

10

;;; presented.

11
12

(prn 10 )

13

(prn (+ 5 3 4) )

14

(prn (- 9 1) )

15

(prn (/ 6 2) )

16

(prn (+ (* 2 4) (- 4 6)) )

17
18

(define a 3)

19

(define b (+ a 1))

20
21

(prn (+ a b (* a b)) )

22

(prn (= a b) )

23
24

(prn (if (and (> b a) (< b (* a b)))

25

26

a) )

27
28

(prn (cond ((= a 4) 6)

29

((= b 4) (+ 6 7 a))

30

(else 25)) )

31

(prn (+ 2 (if (> b a) b a)) )

32
33

(prn (* (cond ((> a b) a)

34
35

((< a b) b)

36

(else -1))

37

(+ a 1)) )

38
39

;; *EOF*

## ./sicp_ch1_e1-1.scm
10
12
8
3
6
19
#f
4
16
6
16

1.1.2

Naming and the Environment

Exercise 1.2. Translate the following expression into prefix form


5 + 1/2 + (2 (3 (6 + 1/5)))
3 (6 2) (2 7)

#!/usr/bin/csi -s

;; sicp_ch1_e1-2.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 1.2. Translate the following expression into prefix form

;;;

10

;;;

5 + 1/2 + (2 - (3 - (6 + 1/5) ) )

11

;;;

---------------------------------

(1)

12

;;;

3 * ( 6 - 2 ) * ( 2 - 7 )

13
14
15

(prn

16

(/

17

(+ 5 1/2 (- 2 (- 3 (+ 6 1/5) ) ) )

18

(* 3 (- 6 2) (- 2 7) )
)

19
20

21
22

;; *EOF*

## ./sicp_ch1_e1-2.scm
-0.178333333333333

1.1.3

Evaluating Combinations

Exercise 1.3. Define a procedure that takes three numbers as arguments and returns the sum of the squares
of the two larger numbers.

#!/usr/bin/csi -s

;; sicp_ch1_e1-3.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 1.3. Define a procedure that takes three numbers as arguments and returns the sum of the

;;; squares of the two larger numbers.

10
11

;; suares and sum

12

(define (my-square x) (map (lambda (x) (* x x)) x) )

13

(define (my-sum x) (apply + x) )

14
15

;; two methods for computing the sum of squares

16

(define (ss-1 x) ((compose my-sum my-square) x))

17

(define (ss-2 x) (apply + (map (lambda (x) (* x x )) x) ) )

18
19

;; selection N elements from a list

(define (take x N)

20

(if (> N 1)

21
22

(cons (car x) (take (cdr x) (- N 1)))

23

(list (car x))


)

24

25
26
27

;; selection for top N given operand

28

(define (top x pred? N) (take (sort x pred?) N) )

29
30

;; sum of sqares for top 2 largest elements in list

31

(define (topss-1 x) ((compose ss-2 (lambda (x) (top x > 2)) ) x))

32

(define (topss-2 x) (ss-2 (top x > 2)) )

33
34

;; test solution

35

(define x (3 5 2 9 1) )

36
37

(prn (topss-1 x) )

38

(prn (topss-2 x) )

39
40

(assert (= (ss-1 x) (ss-2 x) ) )

41

(assert (= (ss-1 x) (ss-2 x) ) )

42

(assert (= (topss-1 x) (topss-2 x) ) )

43

(assert (= (topss-1 x) (topss-2 x) ) )

44
45

;; *EOF*

## ./sicp_ch1_e1-3.scm
106
106

1.1.4

Compound Procedures

Exercise 1.4. Observe that our model of evaluation allows for combinations whose operators are compound
expressions. Use this observation to describe the behavior of the following procedure:
(define (a-plus-abs-b a b)
((if (< b 0) + -) a b))

#!/usr/bin/csi -s

;; sicp_ch1_e1-4.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 1.4. Observe that our model of evaluation allows for combinations whose operators are

;;; compound expressions. Use this observation to describe the behavior of the following procedure:

10

;;; (define (a-plus-abs-b a b)

11

;;; ((if (> b 0) + -) a b))

12

(define (a-plus-abs-b a b)

13

((if (> b 0) + -) a b))

14
15
16

(prn (a-plus-abs-b 5 +2) )

17

(prn (a-plus-abs-b 5 -2) )

18

;; *EOF*

19

## ./sicp_ch1_e1-4.scm
7
7

1.1.5

The Substitution Model for Procedure Application

Exercise 1.5. Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using
applicative-order evaluation or normal-order evaluation. He defines the following two procedures:
(define (p) (p))
(define (test x y)
(if (= x 0)
0
y))
Then he evaluates the expression
(test 0 (p))
What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior
will he observe with an interpreter that uses normal-order evaluation? Explain your answer. (Assume that
the evaluation rule for the special form if is the same whether the interpreter is using normal or applicative
10

order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)

#!/usr/bin/csi -s

;; sicp_ch1_e1-5.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 1.5. Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with
,

is

;;; using applicative-order evaluation or normal-order evaluation. He defines the following two

10

;;; procedures:

11

;;;

(define (p) (p))

12

;;;

(define (test x y)

13

;;;

14

;;;

15

;;;

y))

16

;;; Then he evaluates the expression

17

;;;

18

;;; What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What

19

;;; behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer.

20

;;; (Assume that the evaluation rule for the special form if is the same whether the interpreter is using

21

;;; normal or applicative order: The predicate expression is evaluated first, and the result determines

22

;;; whether to evaluate the consequent or the alternative expression.)

(if (= x 0)

(test 0 (p))

23
24

(define (p) (p))

; infinite recursion

25
26
27

(define (test x y)
(if (= x 0)

28

29

y))

30
31

(prn(test 0 (p)) ) ; infinite loop

32
33

(prn (p) )

; infinite loop

34
35

;; *EOF*

11

Exercise 1.6. Alyssa P. Hacker doesnt see why if needs to be provided as a special form. Why cant I
just define it as an ordinary procedure in terms of cond? she asks. Alyssas friend Eva Lu Ator claims this
can indeed be done, and she defines a new version of if:

(define (new-if predicate then-clause else-clause)


(cond (predicate then-clause)
(else else-clause)))
Eva demonstrates the program for Alyssa:

(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
Delighted, Alyssa uses new-if to rewrite the square-root program:

(new-if (= 1 1) 0 5)
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
What happens when Alyssa attempts to use this to compute square roots? Explain.

Calls to the compound procedure new-if are applicatively evaluated, that is evaluated first and then
passed as arguments to the procedure. The predicates and clauses to cond, and thus results in infinite
recursion of unintended clause.

This is not the case with the intrinsic if procedure, which performs normal evaluation of the expression.

new-if (predicate, if-clause, else-clause) =

12

if-clause

if predicate

then-clause

otherwise

(2)

One possible correction for new-if, here, new-if-im, is to accept quasi-quoted arguments, and then eval
them.


new-ifim predicate, if-clause, else-clause =

eval (if-clause)

if eval (predicate)

eval (then-clause)

otherwise

where predicate, if-clause, and else-clause are quasi-quoted expressions.

#!/usr/bin/csi -s

;; sicp_ch1_e1-6.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 1.6.

Alyssa P. Hacker doesnt see why if needs to be

;;; provided as a special form. Why cant I just define it as an

10

;;; ordinary procedure in terms of cond? she asks. Alyssas friend

11

;;; Eva Lu Ator claims this can indeed be done, and she defines a new

12

;;; version of if:

13
14

;;;

15

;;;

16

;;;

(define (new-if predicate then-clause else-clause)


(cond (predicate then-clause)
(else else-clause)))

17
18

;;; Eva demonstrates the program for Alyssa:

19
20

;;;

21

;;;

(new-if (= 2 3) 0 5)
5

22
23

;;;

24

;;;

(new-if (= 1 1) 0 5)
0

25
26

;;; Delighted, Alyssa uses new-if to rewrite the square-root program:

27
28

;;;

29

;;;

(define (sqrt-iter guess x)


(new-if (good-enough? guess x)

13

(3)

30

;;;

guess

31

;;;

(sqrt-iter (improve guess x)

32

;;;

x)))

33
34

;;;

35

;;;

What happens when Alyssa attempts to use this to compute square


roots? Explain.

36
37

;; =======================================================

38

;; EXPERIMENT

39

;; =======================================================

40
41

(define (sqrt-iter-if guess x)

42

(if (good-enough? guess x)

43

guess

44

(sqrt-iter-if (improve guess x) x)))

45
46

(define (good-enough? guess x)


(< (abs (- (square guess) x)) 0.001))

47
48
49

(define (improve guess x)


(average guess (/ x guess)))

50
51
52

(define (average x y)
(/ (+ x y) 2))

53
54
55

(define (cond-trace p1 c1 p2 c2 ow)


(cond

56
57

((p1) (c1))

58

((p2) (c2))

59

(else (ow))

60

))

61
62

;; =======================================================

63

;; NEW IF

64

;; =======================================================

65
66

;; Calls to the compound procedure new-if are applicatively

67

;;

evaluated, that is evaluated first and then passed as

68

;;

arguments to the procedure.

69

;;

to cond, and thus results in infinite recursion of

The predicates and clauses

14

70

;;

unintended clause.

71

;;

72

;; This is not the case with the intrinsic if procedure,

73

;;

which performs normal evaluation of the expression.

74
75

(define (new-if predicate then-clause else-clause)


(cond (predicate then-clause)

76

(else else-clause)))

77
78
79

(define (sqrt-iter guess x)


(new-if (good-enough? guess x)

80
81

guess

82

(sqrt-iter (improve guess x) x)))

83
84

;; =======================================================

85

;; IMPROVED NEW IF

86

;; =======================================================

87
88

;; One possible correction for new-if is to accept

89

;;

quasi-quoted arguments, and then eval them.

90
91
92

(define (im-new-if q-predicate q-then-clause q-else-clause)


(cond ((eval q-predicate) (eval q-then-clause))
(else (eval q-else-clause))))

93
94
95
96

(define (im-sqrt-iter guess x)


(im-new-if (good-enough? ,guess ,x)

97

,guess

98

(im-sqrt-iter (improve ,guess ,x) ,x)))

99
100

;; =======================================================

101

;; TESTS

102

;; =======================================================

103
104

(bar)

105

(prn "example:")

106

(prn (new-if (= 2 3) 0 5) ) ; 5

107

(prn (new-if (= 1 1) 0 5) ) ; 0

108

(hr)

109

(prn "example 1.6: applied")

15

110
111

(prnvar "sqrt-iter-if 9"

(sqrt-iter-if 9 9))

; (prnvar "sqrt-iter-new-if 9" (sqrt-iter

9 9)) ; infinite loop

112

(hr)

113

(prn "example 1.6: cond-trace 1")

114

(define (p1) (let ((val #t)) (begin (prnvar "predicate-1" val) val)))

115

(define (c1) (prn "clause-1"))

116

(define (p2) (let ((val #t)) (begin (prnvar "predicate-2" val) val)))

117

(define (c2) (prn "clause-2"))

118

(define (ow) (prn "otherwise"))

119

(cond-trace p1 c1

120

(hr)

121

(prn "example 1.6: cond-trace 2")

122

(define (p1) (let ((val #f)) (begin (prnvar "predicate-1" val) val)))

123

(define (c1) (prn "clause-1"))

124

(define (p2) (let ((val #t)) (begin (prnvar "predicate-2" val) val)))

125

(define (c2) (prn "clause-2"))

126

(define (ow) (prn "otherwise"))

127

(cond-trace p1 c1

128

(hr)

129

(prn "example 1.6: cond-trace otherwise")

130

(define (p1) (let ((val #f)) (begin (prnvar "predicate-1" val) val)))

131

(define (c1) (prn "clause-1"))

132

(define (p2) (let ((val #f)) (begin (prnvar "predicate-2" val) val)))

133

(define (c2) (prn "clause-2"))

134

(define (ow) (prn "otherwise"))

135

(cond-trace p1 c1

136

(hr)

137

(prn "example 1.6: improved, using quasi-quote and eval")

138

(prnvar "sqrt-iter-new-if-im 9" (im-sqrt-iter 9 9))

139

(bar)

p2 c2 ow)

p2 c2 ow)

p2 c2 ow)

140
141

;; *EOF*

16

## ./sicp_ch1_e1-6.scm
================================================================================
example:
5
0
-------------------------------------------------------------------------------example 1.6: applied
sqrt-iter-if 9 := 3.00009155413138
-------------------------------------------------------------------------------example 1.6: cond-trace 1
predicate-1 := #t
clause-1
-------------------------------------------------------------------------------example 1.6: cond-trace 2
predicate-1 := #f
predicate-2 := #t
clause-2
-------------------------------------------------------------------------------example 1.6: cond-trace otherwise
predicate-1 := #f
predicate-2 := #f
otherwise
-------------------------------------------------------------------------------example 1.6: improved, using quasi-quote and eval
sqrt-iter-new-if-im 9 := 3.00009155413138
================================================================================

1.1.6

Conditional Expressions and Predicates

1.1.7

Example: Square Roots by Newtons Method

Exercise 1.7. The good-enough? test used in computing square roots will not be very effective for finding
the square roots of very small numbers. Also, in real computers, arithmetic operations are almost always
performed with limited precision. This makes our test inadequate for very large numbers. Explain these
statements, with examples showing how the test fails for small and large numbers. An alternative strategy
for implementing good-enough? is to watch how guess changes from one iteration to the next and to stop
when the change is a very small fraction of the guess. Design a square-root procedure that uses this kind of
end test. Does this work better for small and large numbers?

Newtons method:
f (xn )
f 0 (xn )

(4)

x2n guess
2xn

(5)

xn+1 = xn
Applied to square root:
xn+1 = xn

17

#!/usr/bin/csi -s

;; sicp_ch1_e1-5.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 1.5. Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with
,

is

;;; using applicative-order evaluation or normal-order evaluation. He defines the following two

10

;;; procedures:

11

;;;

(define (p) (p))

12

;;;

(define (test x y)

13

;;;

14

;;;

15

;;;

y))

16

;;; Then he evaluates the expression

17

;;;

18

;;; What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What

19

;;; behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer.

20

;;; (Assume that the evaluation rule for the special form if is the same whether the interpreter is using

21

;;; normal or applicative order: The predicate expression is evaluated first, and the result determines

22

;;; whether to evaluate the consequent or the alternative expression.)

(if (= x 0)

(test 0 (p))

23
24

(define (p) (p))

; infinite recursion

25
26
27

(define (test x y)
(if (= x 0)

28

29

y))

30
31

; (prn(test 0 (p)) ) ; infinite loop

32
33

; (prn (p) )

; infinite loop

34
35

;; *EOF*

## ./sicp_ch1_e1-7.scm

18

1.1.8

1.2

Procedures as Black-Box Abstractions

Procedures and the Processes They Generate

1.2.1

Linear Recursion and Iteration

Exercise 1.9: Each of the following two procedures defines a method for adding two positive integers in terms
of the procedures inc, which increments its argument by 1, and dec, which decrements its argument by 1.

#!/usr/bin/csi -s

;; sicp_ch1_e1-9.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 1.9: Each of the following two procedures defines a method for adding two positive integers
,

in terms of the procedures inc, which increments its argument by 1, and dec, which decrements its

argument by 1.

9
10

(define (my-inc x) (begin (prn "inc") (+ x 1) ) ) ; inc with side effects

11

(define (my-dec x) (begin (prn "dec") (- x 1) ) ) ; dec with side effects

12
13

(define (recursive-+ a b)
(if (= a 0) b (my-inc (recursive-+ (my-dec a) b))))

14
15
16

(define (iterative-+ a b)
(if (= a 0) b (iterative-+ (my-dec a) (my-inc b)))) ; proper tail recursion

17
18
19

;;; Using the substitution model, illustrate the process gener- ated by each procedure in evaluating (+ 4
,

20

5).

;;; Are these processes iterative or recursive?

21
22

(define a 4)

23

(define b 5)

24
25

(prnvar "a" a )

26

(prnvar "b" b )

27

(prnvar "recursive" (recursive-+ a b) ) ; recursive

28

(prnvar "iterative" (iterative-+ a b) ) ; iterative

19

29
30

;; *EOF*

## ./sicp_ch1_e1-9.scm
a := 4
b := 5
dec
dec
dec
dec
inc
inc
inc
inc
recursive := 9
dec
inc
dec
inc
dec
inc
dec
inc
iterative := 9

Exercise 1.11: A function f is defined by the rule that

f (n) =

n<3
(6)

1f (n 1) + 2f (n 2) + 3f (n 3)

otherwise

Write a procedure that computes f by means of a recursive process. Write a procedure that computes f
by means of an iterative process.

Representing State Space Transitions

Direct Iterative Implementation

f (n) := s0

20

(7)

with state transition


T

s0 s0 + 2s1 + 3s2

s1 s0

s2 s1

(8)

and initial conditions


S0

s0 := 2

s := 1
1

s2 := 0

(9)

Linear Feedback Shift Register (LFSR) representation

f (n, s)

nth s

n=0

(10)

f n 1, nth
1 1 (s), [1, 2, 3]

x, y ,

xk yk = xk y k

otherwise

(11)

nth
k , xk

(12)

k (x) , x(n+k)mod|x| n x

(13)

21

Figure 1: Linear Feedback Shift Register (LFSR)

State Space Representation

Xk = FXk1

F
Xk
Xk1
0
x0 1 2 3 x0
0

x = 1 0 0 x
1
1
0

x2
0 1 0
x2

22

(14)

(15)

where
X0
2

X0 =
1

(16)

so

Xk = FXk1 = F (FXk2 ) = F (F (FXk3 )) = = FN X0

#!/usr/bin/csi -s

;; sicp_ch1_e1-1.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 1.11: A function f is defined by the rule that

;;;

10

;;;

11

;;; f(n)={ f(n-1)+2f(n-2)+3f(n-3) if n>3

12

;;;

13

;;; Write a procedure that computes f by means of a recursive process. Write a procedure that computes f
,

14

{ n

if n<3,

by means of an iterative process.

;;;

15
16

;; =======================================================

17

;; RECURSIVE

18

;; =======================================================

19
20

;;

{ n

21

;; f(n)={

22

;;

{ f(n-1) + 2f(n-2) + 3f(n-3)

if n<3

otherwise

23
24

;; f(n) recursive form

25

(define (f-recursive n)

26

(if (< n 3)

27

28

(+ (f-recursive (- n 1)) (* 2 (f-recursive (- n 2)) ) (* 3 (f-recursive (- n 3)) ) )

23

(17)

29
30

31
32

;; =======================================================

33

;; DIRECT ITERATIVE

34

;; =======================================================

35
36

;; NB: f(n) = 1*f(n-1) + 2*f(n-2) + 3*f(n-3)

37

;;

38

;;

39

;;

40

;;

s0 <- s0 + 2*s1 + 3*s2

41

;;

s1 <- s0

42

;;

s2 <- s1

f(n) = s0
state transition

43
44
45

;; f(n) direct form

46

(define (f-direct n)
(f-direct-iter 2 1 0 n) ; initial state vector [ 0 1 2 ]

47
48

49
50

;; f(n) direct form iteration step

51

(define (f-direct-iter s0 s1 s2 n)

52

(if (< n 3)

53

s0

54

(f-direct-iter

55

(+ (* 1 s0) (* 2 s1) (* 3 s2) )

56

s0

57

s1

58

(- n 1)

59
60
61

) ; next
) ; iteration test
) ; direct form

62
63

;; however, in general, f(n) can be thought of as:

64
65

;; =======================================================

66

;; Linear Feedback Shift Register (LFSR)

67

;; =======================================================

68

24

69

;; 1) Linear Feedback Shift Register (LFSR)

70

;;

71

;;

72

;;

previous integers up to n with initial register state x0 := [ 0 1 2 ]

73

;;

and polynomial coefficients given by a := [ 1 2 3 ]

74

;;

75

;;

76

;;

77

;;

78

;;

79

;;

80

;;

81

;;

82

;;

83

;;

84

;;

85

;;

f[n] is a Linear Feedback Shift Register (LFSR) operating on the sequence of

x[k] = LFSR(x[k-1], a)
= program { circshift(x), x_0 = <x,a> }

f(n) = CAR of x[n]

where

x[0] := [ 0 1 2 ]

a := [ 1 2 3 ]

86
87
88

;; f(n) LFSR form

89

(define (f-lfsr n)

90

(let (

91

(a

92

(x0 (2 1 0)) ; initial state

93

(k

(1 2 3)) ; coefficients

(- n 2))

; k transitions

94

) ; bindings

95

(f-lfsr-iter x0 a k)

x0 := [ 0 1 2 ]
k := n - 2

) ; let

96
97

a := [ 1 2 3 ]

98
99
100

;; f(n) LFSR form iteration step


(define (f-lfsr-iter x a k)

101

(if (= k 0)

102

(car x)

103

(f-lfsr-iter (lfsr x a) a (- k 1))


)

104
105

106
107

;; =======================================================

108

;; State Space Representation

25

109

;; =======================================================

110
111

;; 2) State Space Representaiton

112

;;

113

;;

114

;;

representation F := [ 0 1 0 ; 0 0 1 ; 1

115

;;

initial conditions x0 := [ 0 1 2 ]

116

;;

117

;;

118

;;

= F * ( F * x[k-2] )

119

;;

= F * ( F * ( F * x[k-3] ) )

120

;;

= ...

121

;;

= F^n * x0

122

;;

123

;;

124

;;

125

;;

126

;;

127

;;

128

;;

129

;;

[ 1 2 3 ]

130

;;

F := [ 1 0 0 ]

131

;;

[ 0 1 0 ]

132

;;

f[n] is the effect of a system up to time n with a given state space


2 3 ], and with

x[k] = F * x[k-1]

f(n) = x[n]

where

x[0] := [ 2 1 0 ]

133
134

;; version #1, using Iverson matrix representation

135
136
137

(define (f-ss n)
(let (

138

(t_ref 2)

; reference time relative to state space

139

(x0 (2 1 0)) ; initial state x0

140

(F

(1 2 3

141

1 0 0

142

0 1 0 )

143

) ; state transition matrix F

144

(dimF (3 3)) ; F is MxN = 3x3

145

(dimX (3 1)) ; X is Nx1 = 3x1

146

) ; bindings

147

(car (f-ss-iter F dimF x0 dimX (- n t_ref)) )

148

) ; let

26

149

150
151

(define (f-ss-iter F dimF x dimX k)


(if (< k 1)

152
153

154

;; x[k] = F * x[k-1]

155

(f-ss-iter F dimF (mat-* F dimF x dimX) dimX (- k 1))


) ; each

156
157

) ; ff-ss-iter

158
159

(define n 12)

160
161

(prnvar "recursive f(n)" (f-recursive n) )

; recursive

162

(prnvar "

direct f(n)" (f-direct n) )

; direct

163

(prnvar "

LFSR f(n)" (f-lfsr n) )

164

(prnvar "

SS f(n)" (f-ss n) )

; LFSR
; state space

165
166

;; *EOF*

## ./sicp_ch1_e1-11.scm
recursive
direct
LFSR
SS

f(n)
f(n)
f(n)
f(n)

:=
:=
:=
:=

10661
10661
10661
10661

1.2.2

Tree Recursion

1.2.3

Orders of Growth

1.2.4

Exponentiation

Exercise 1.16: Design a procedure that evolves an iterative exponentiation process that uses successive
squaring and uses a logarithmic number of steps, as does fast-expt. (Hint: Using the observation that
n
n 2
b 2 = b2 2 , keep, along with the exponent n and the base b, an additional state variable a, and define
the state transformation in such a way that the product a bn is unchanged from state to state. At the
beginning of the process a is taken to be 1, and the answer is given by the value of a at the end of the
process. In general, the technique of defining an invariant quantity that remains unchanged from state to

27

state is a powerful way to think about the design of iterative algorithms.)

fbenchmark (x, n) =

if n is zero

2
fbenchmark x, n2

fbenchmark (x, n 1)2

if n is even, nonzero

(18)

if n is odd

may be restructured as

f (x, n) = fk (x, n, p)

(19)

where

fk (x, n, p) =

#!/usr/bin/csi -s

;; sicp_ch1_e1-16.scm

;; Mac Radigan

if n is zero


n
f
x,
,
p
k
2

fk (x, n 1, p x)

(20)

if n is even, nonzero
if n is odd

4
5

(load "../library/util.scm")

(import util)

7
8
9

;;; Exercise 1.16.

Design a procedure that evolves an iterative exponentiation process that uses

successive squaring and uses a logarithmic number of steps, as does fast-expt.

observation that (bn/2)2 = (b2)n/2, keep, along with the exponent n and the base b, an additional

state variable a, and define the state transformation in such a way that the product a bn is

unchanged from state to state. At the beginning of the process a is taken to be 1, and the answer is

given by the value of a at the end of the process. In general, the technique of defining an invariant

quantity that remains unchanged from state to state is a powerful way to think about the design of

iterative algorithms.)

10
11

;; ==============================================================================

12

;; benchmark from book:

13

;;

14

;;

if n is zero

28

(Hint: Using the

15

;;

f(x,n) = {

16

;;

17

;;

f(x,n/2)^2

if n is even, nonzero

f(x,n-1)

if n is odd

18

(define (even? n)

19

(= (remainder n 2) 0))

20
21

(define (ref-fast-expt b n)

22

(cond ((= n 0) 1)

23

((even? n) (square (ref-fast-expt b (/ n 2)) ))

24

(else (* b (ref-fast-expt b (- n 1))) )))

25
26
27
28

;; ==============================================================================

29

;; propagating product up through recursion:

30

;;

31

;;

32

;;

f(x,n,p) = {

33

;;

34

;;

if n is zero

f(x,n/2,p)

if n is even, nonzero

f(x,n-1,x*p)

if n is odd

35
36
37

(define (fast-expt-iter b n p)
(cond ((= n 0) p)
((even? n) (fast-expt-iter (* b b) (/ n 2) p) )

38

(else (fast-expt-iter b (- n 1) (* b p)) )))

39
40
41

(define (sep-fast-expt b n)

42

(fast-expt-iter b n 1))

43
44
45

;; ==============================================================================

46

;; encapsulated as a single function

47
48

(define (fast-expt b n)

49

;;

50

;;

f(x,n,p) = {

51

;;

52

(define (f b n p)

53
54

if n is zero

f(x,n/2,p)

if n is even, nonzero

f(x,n-1,x*p)

if n is odd

(cond ((= n 0) p)
((even? n) (f (* b b) (/ n 2) p) )

29

(else (f b (- n 1) (* b p)) )))

55

(f b n 1) ; call

56
57

58
59
60

;; ==============================================================================

61

;; applying self-referencing lambdas

62
63

(define (sr-fast-expt b n)

64

(define f (lambda (@f)


(lambda (b n p)

65

(cond ((= n 0) p )

66

((even? n) ((f f) (* b b) (/ n 2) p) )

67

(else ((f f) b (- n 1) (* b p)) ))

68

) ; f(x,n)

69
70

)) ; self

71

((f f) b n 1)

72

73
74
75

;; ==============================================================================

76

;; with hygenic macros

77
78
79
80
81

(define-syntax call
(syntax-rules ()
((_ f)
(f f))))

82
83
84
85
86

(define-syntax fn
(syntax-rules ()
((_ signature self fn-base fn-iter)
(define signature

87

(define self (lambda (@self) fn-iter))

88

fn-base

89

) )))

90
91

(fn (mac-fast-expt b n) f

92

;; f(b,n,1)

93

((call f) b n 1)

94

;; f(b,n,p)

30

(lambda (b n p)

95

(cond ((= n 0) p )

96
97

((even? n) ((call f) (* b b) (/ n 2) p) )

98

(else ((call f) b (- n 1) (* b p)) ))


) ; f(x,n)

99
100

101
102
103

;; ==============================================================================

104

;; test:

105

(define b 2)

106

(define n 8)

107
108

(bar)

109

(prn "intrinsic:")

110

(prn (expt b n)) ;

111

(hr)

112

(prn "reference:")

113

(prn (ref-fast-expt b n)) ;

114

(hr)

115

(prn "example 1-16: (separate functions)")

116

(prn (sep-fast-expt b n)) ;

117

(hr)

118

(prn "example 1-16: (nested functions)")

119

(prn (fast-expt b n)) ;

120

(hr)

121

(prn "example 1-16 (self-referencing lambdas):")

122

(prn (sr-fast-expt b n)) ;

123

(hr)

124

(prn "example 1-16 (using macros):")

125

(prn (mac-fast-expt b n) )

126

(bar)

127
128

;; *EOF*

31

## ./sicp_ch1_e1-16.scm
================================================================================
intrinsic:
256
-------------------------------------------------------------------------------reference:
256
-------------------------------------------------------------------------------example 1-16: (separate functions)
256
-------------------------------------------------------------------------------example 1-16: (nested functions)
256
-------------------------------------------------------------------------------example 1-16 (self-referencing lambdas):
256
-------------------------------------------------------------------------------example 1-16 (using macros):
256
================================================================================

1.2.5

Greatest Common Divisors

1.2.6

Example: Testing for Primality

1.3

Formulating Abstractions with Higher-Order Procedures

1.3.1

Procedures as Arguments

1.3.2

Constructing Procedures Using Lambda

1.3.3

Procedures as General Methods

1.3.4

Procedures as Returned Values

Exercise 1.42. Let f and g be two one-argument functions. The composition f after g is defined to be the
function x 7 f (g (x)). Define a procedure compose that implements composition. For example, if inc is a
procedure that adds 1 to its argument, ((compose square inc) 6)
1

#!/usr/bin/csi -s

;; sicp_ch1_e1-42.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

32

;;; Exercise 1.42. Let f and g be two one-argument functions. The composition f after g is defined to be

;;; the function x f(g(x)). Define a procedure compose that implements composition. For example, if

10

;;; inc is a procedure that adds 1 to its argument,

11

;;; ((compose square inc) 6)

12
13

;;; from util.scm

14

; (define (square x) (map (lambda (x) (* x x)) x) )

15

; (define (inc x) (+ x 1))

16

; (define ((compose f g) x) (f (g x)))

17

(prn ((compose square inc) 6) ) ; 49

18
19
20

;; *EOF*

## ./sicp_ch1_e1-42.scm
49

33

Building Abstractions with Data

2.1

Introduction to Data Abstraction

2.1.1

Example: Arithmetic Operations for Rational Numbers

Exercise 2.1. Define a better version of make-rat that handles both positive and negative arguments. Makerat should normalize the sign so that if the rational number is positive, both the numerator and denominator
are positive, and if the rational number is negative, only the numerator is negative.
1

#!/usr/bin/csi -s

;; sicp_ch2_e2-1.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 2.1. Define a better version of make-rat that handles both positive and negative

;;; arguments. Make-rat should normalize the sign so that if the rational number is positive, both the

10

;;; numerator and denominator are positive, and if the rational number is negative, only the numerator is

11

;;; negative.

12
13
14
15
16

(define (add-rat x y)
(make-rat (+ (* (numer x) (denom y))
(* (numer y) (denom x)))
(* (denom x) (denom y))))

17
18
19
20
21

(define (sub-rat x y)
(make-rat (- (* (numer x) (denom y))
(* (numer y) (denom x)))
(* (denom x) (denom y))))

22
23
24
25

(define (mul-rat x y)
(make-rat (* (numer x) (numer y))
(* (denom x) (denom y))))

26
27
28
29

(define (div-rat x y)
(make-rat (* (numer x) (denom y))
(* (denom x) (numer y))))

30
31

(define (equal-rat? x y)

34

32
33

(= (* (numer x) (denom y))


(* (numer y) (denom x))))

34
35
36

(define (signum x)
(if (> x 0) +1 -1) )

37
38
39

(define (make-rat num denom)


(cons (* (signum (* num denom)) (abs (/ num (gcd num denom)))) (abs (/ denom (gcd num denom)))) )

40
41
42

(define (numer x)
(car x))

43
44
45

(define (denom x)
(cdr x))

46
47

(define x1 (make-rat

2))

; x1 =

1/2

48

(define x2 (make-rat

4))

; x2 =

1/4

49

(define x3 (make-rat

4))

; x3 =

2/4

50

(define x4 (make-rat -1

2))

; x4 = -1/2

51

(define x5 (make-rat

1 -4))

; x5 = -1/4

52

(define x6 (make-rat -2 -4))

; x6 =

2/4

53
54

(prvar "x1 = 1/2 " x1)

1/2

55

(prvar "x2 = 1/4 " x2)

1/4

56

(prvar "x3 = 2/4 " x3)

2/4

57

(prvar "x4 = -1/2 " x4) ; -1/2

58

(prvar "x5 = -1/4 " x5) ; -1/4

59

(prvar "x6 = 2/4 " x6)

2/4

60
61

(ck "x1*x2" equal-rat? (mul-rat x1 x2) (make-rat 1 8))

62

(ck "x1*x4" equal-rat? (mul-rat x1 x4) (make-rat -1 4)) ;

63

(ck "x4*x5" equal-rat? (mul-rat x4 x5) (make-rat 1 8))

64

(ck "x5*x6" equal-rat? (mul-rat x5 x6) (make-rat -1 8)) ; -1/4 *

65
66

;; *EOF*

## ./sicp_ch2_e2-1.scm

35

1/2 *

1/4 = 1/8

1/2 * -1/2 = 1/4

; -1/2 * -1/4 = 1/8


2/4 = -1/8

2.1.2

Abstraction Barriers

Exercise 2.2. Consider the problem of representing line segments in a plane. Each segment is represented
as a pair of points: a starting point and an ending point. Define a constructor make-segment and selectors
start-segment and end-segment that define the representation of segments in terms of points. Furthermore,
a point can be represented as a pair of numbers: the x coordinate and the y coordinate. Accordingly, specify
a constructor make-point and selectors x-point and y-point that define this representation. Finally, using
your selectors and constructors, define a procedure midpoint-segment that takes a line segment as argument
and returns its midpoint (the point whose coordinates are the average of the coordinates of the endpoints).
To try your procedures, youll need a way to print points:
1

#!/usr/bin/csi -s

;; sicp_ch2_e2-2.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 2.2. Consider the problem of representing line segments in a plane. Each segment is

;;; represented as a pair of points: a starting point and an ending point. Define a constructor

10

;;; make-segment and selectors start-segment and end-segment that define the representation

11

;;; of segments in terms of points. Furthermore, a point can be represented as a pair of numbers: the x

12

;;; coordinate and the y coordinate. Accordingly, specify a constructor make-point and selectors

13

;;; x-point and y-point that define this representation. Finally, using your selectors and

14

;;; constructors, define a procedure midpoint-segment that takes a line segment as argument and

15

;;; returns its midpoint (the point whose coordinates are the average of the coordinates of the
,

16

endpoints).

;;; To try your procedures, youll need a way to print points:

17
18

(define (print-point p)

19

(newline)

20

(display "(")

21

(display (x-point p))

22

(display ",")

23

(display (y-point p))

24

(display ")")

25

(newline)

26

27

36

28

;; point construct

29

(define (make-point x y)
(cons x y))

30
31
32

(define (x-point pt)


(car pt))

33
34
35

(define (y-point pt)


(cdr pt))

36
37
38

(define (equal-point? pt1 pt2)


(and

39

(= (x-point pt1) (x-point pt2))

40

(= (y-point pt1) (y-point pt2))

41

42
43

44
45

;; segment construct

46

(define (make-segment pt1 pt2)


(cons pt1 pt2))

47
48
49

(define (start-segment seg)


(car seg))

50
51
52

(define (end-segment seg)


(cdr seg))

53
54
55

(define (midpoint-segment seg)


(make-point

56
57

(/ (+ (x-point (start-segment seg)) (x-point (end-segment seg)) ) 2)

58

(/ (+ (y-point (start-segment seg)) (y-point (end-segment seg)) ) 2)


)

59
60

61
62

;; test constructs

63

(define pt-00 (make-point 0 0)) ; (0, 0) origin

64

(define pt-10 (make-point 1 0)) ; (1, 0)

65

(define pt-01 (make-point 0 1)) ; (0, 1)

66
67

(define s-x

(make-segment pt-00 pt-10)) ; (0,0) -> (0,1)

37

68

(define s-y

(make-segment pt-00 pt-01)) ; (0,0) -> (1,0)

69

(define s-xy (make-segment pt-10 pt-01)) ; (1,0) -> (1,0)

70
71

(define pt-mid (midpoint-segment s-xy)) ; (0.5,0.5)

72
73

(print-point pt-mid)

74
75

(ck "midpoint" equal-point? pt-mid (make-point 0.5 0.5)) ; -1/4 *

2/4 = -1/8

76
77

;; *EOF*

## ./sicp_ch2_e2-2.scm

(0.5,0.5)
midpoint = (0.5 . 0.5)

; ok: expected (0.5 . 0.5)

Exercise 2.3. Implement a representation for rectangles in a plane. (Hint: You may want to make use
of exercise 2.2.) In terms of your constructors and selectors, create procedures that compute the perimeter
and the area of a given rectangle. Now implement a different representation for rectangles. Can you design
your system with suitable abstraction barriers, so that the same perimeter and area procedures will work
using either representation?
1

#!/usr/bin/csi -s

;; sicp_ch2_e1-1.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 2.3. Implement a representation for rectangles in a plane. (Hint: You may want to make use

;;; of exercise 2.2.) In terms of your constructors and selectors, create procedures that compute the

10

;;; perimeter and the area of a given rectangle. Now implement a different representation for rectangles.

11

;;; Can you design your system with suitable abstraction barriers, so that the same perimeter and area

12

;;; procedures will work using either representation?

13
14

;; *EOF*

## ./sicp_ch2_e2-3.scm

38

2.1.3

What Is Meant by Data?

2.1.4

Extended Exercise: Interval Arithmetic

2.2

Hierarchical Data and the Closure Property

Exercise 2.17. Define a procedure last-pair that returns the list that contains only the last element of a given
(nonempty) list:
1

#!/usr/bin/csi -s

;; sicp_ch2_e2-17.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 2.17.

Define a procedure last-pair that returns the list

;;; that contains only the last element of a given (nonempty) list:

10
11

(define (last-pair x)
(if (null? x)

12
13

#f ; case empty list

14

(if (null? (cdr x))

15

(car x)

16

(last-pair (cdr x))


)

17

18
19

20
21

;; =======================================================

22

;; TESTS

23

;; =======================================================

24
25

(bar)

26

(prnvar "(23 72 149 34)" (last-pair (list 23 72 149 34)) ) ; 34

27

(prnvar "(

28

(bar)

)" (last-pair (list)) )

; #f

29
30

;; *EOF*

39

## ./sicp_ch2_e2-17.scm
================================================================================
(23 72 149 34) := 34
(
) := #f
================================================================================

Exercise 2.18. Define a procedure reverse that takes a list as argument and returns a list of the same elements
in reverse order:
1

#!/usr/bin/csi -s

;; sicp_ch2_e2-17.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 2.18.

Define a procedure reverse that takes a list as

;;; argument and returns a list of the same elements in reverse order:

10
11

; ;; my-reverse

12

; (define (my-reverse x)

13

14

(list)

15

(append (my-reverse (cdr x)) (list (car x)))

16

17

; )

(if (null? x)

18
19

;; =======================================================

20

;; TESTS

21

;; =======================================================

22
23

(bar)

24

(prnvar "(1 4 9 16 25)" (my-reverse (list 1 4 9 16 25)) ) ; (25 16 9 4 1)

25

(prnvar "(

26

(bar)

)" (my-reverse (list)) )

; #f

27
28

;; *EOF*

## ./sicp_ch2_e2-18.scm
================================================================================
(1 4 9 16 25) := (25 16 9 4 1)
(
) := ()
================================================================================

40

2.2.1

Representing Sequences

2.2.2

Hierarchical Structures

2.2.3

Sequences as Conventional Interfaces

2.2.4

Example: A Picture Language

Exercise 2.44. Define the procedure up-split used by corner-split. It is similar to right-split, except that it
switches the roles of below and beside.
1

#!/usr/bin/csi -s

;; sicp_ch2_e2-44.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

(use sicp)

9
10

;;; Exercise 2.44.

Define the procedure up-split used by corner-split.

11

;;; It is similar to right-split, except that it switches the roles of below ;;; and beside.

12
13

(define (up-split painter n)

14

(if (= n 0)

15

painter

16

(let

17

( (subimage (up-split painter (- n 1))) )

18

(below painter (beside subimage subimage))


)

19

20
21

22
23

;; =======================================================

24

;; TEST

25

;; =======================================================

26
27

(bar)

28

(prnvar "up-split lena.jpg" "../figures/sicp_ch2_e2-44.png")

29
30
31

(write-painter-to-png (up-split
(image->painter "../figures/lena.jpg") 2)
"../figures/sicp_ch2_e2-44.png")

41

32

(bar)

33
34

;; *EOF*

## ./sicp_ch2_e2-44.scm
================================================================================
up-split lena.jpg := ../figures/sicp_ch2_e2-44.png
Background RRGGBBAA: ffffff00
Area 0:0:256:256 exported to 256 x 256 pixels (90 dpi)
Bitmap saved as: ../figures/sicp_ch2_e2-44.png
================================================================================

Figure 2: Up Split 2

Exercise 2.45. Right-split and up-split can be expressed as instances of a general splitting operation.
Define a procedure split with the property that evaluating
(define right-split (split beside below))
(define up-split (split below beside))
produces procedures right-split and up-split with the same behaviors as the ones already defined.
1

#!/usr/bin/csi -s

;; sicp_ch2_e2-45.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

42

7
8

(use sicp)

9
10

;;; Exercise 2.45.

Right-split and up-split can be expressed as

11

;;; instances of a general splitting operation. Define a procedure

12

;;; split with the property that evaluating

13

;;;

14

;;;

(define right-split (split beside below))

15

;;;

(define up-split (split below beside))

16

;;;

17

;;; produces procedures right-split and up-split with the same

18

;;; behaviors as the ones already defined.

19
20
21

(define (split dir1 dir2)


(lambda (painter n)

22

(if (= n 0)

23

painter

24

(let

25

( (subimage ((split dir1 dir2) painter (- n 1))) )

26

(dir1 painter (dir2 subimage subimage))


) ; let

27
28

) ; if

29

) ; lambda

30

) ; split

31
32

(define right-split (split beside below))

33
34

(define up-split (split below beside))

35
36

;; =======================================================

37

;; TEST

38

;; =======================================================

39
40

(bar)

41

(prnvar "right-split lena.jpg" "../figures/sicp_ch2_e2-45_right.png")

42
43

(write-painter-to-png (right-split
(image->painter "../figures/lena.jpg") 2)
"../figures/sicp_ch2_e2-45_right.png")

44
45

(hr)

46

(prnvar "up-split lena.jpg" "../figures/sicp_ch2_e2-45_up.png")

43

47
48
49
50

(write-painter-to-png (up-split
(image->painter "../figures/lena.jpg") 2)
"../figures/sicp_ch2_e2-45_up.png")
(bar)

51
52

;; *EOF*

## ./sicp_ch2_e2-45.scm
================================================================================
right-split lena.jpg := ../figures/sicp_ch2_e2-45_right.png
Background RRGGBBAA: ffffff00
Area 0:0:256:256 exported to 256 x 256 pixels (90 dpi)
Bitmap saved as: ../figures/sicp_ch2_e2-45_right.png
-------------------------------------------------------------------------------up-split lena.jpg := ../figures/sicp_ch2_e2-45_up.png
Background RRGGBBAA: ffffff00
Area 0:0:256:256 exported to 256 x 256 pixels (90 dpi)
Bitmap saved as: ../figures/sicp_ch2_e2-45_up.png
================================================================================

Figure 3: Right Split 2

44

Figure 4: Up Split 2

Exercise 2.46. A two-dimensional vector v running from the origin to a point can be represented as a
pair consisting of an x-coordinate and a y-coordinate. Implement a data abstraction for vectors by giving a
constructor make-vect and corresponding selectors xcor-vect and ycor-vect. In terms of your selectors and
constructor, implement procedures add-vect, sub-vect, and scale-vect that perform the operations vector
addition, vector subtraction, and multiplying a vector by a scalar:
1

#!/usr/bin/csi -s

;; sicp_ch2_e2-46.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 2.46.

A two-dimensional vector v running from the

;;; origin to a point can be represented as a pair consisting

10

;;; of an x-coordinate and a y-coordinate. Implement a data

11

;;; abstraction for vectors by giving a constructor make-vect

12

;;; and corresponding selectors xcor-vect and ycor-vect. In

13

;;; terms of your selectors and constructor, implement procedures

14

;;; add-vect, sub-vect, and scale-vect that perform the operations

15

;;; vector addition, vector subtraction, and multiplying a vector

16

;;; by a scalar:

17

45

18
19

(define (make-vect x y)
(cons x y))

20
21
22

(define (xcor-vect v)
(car v))

23
24
25

(define (ycor-vect v)
(cdr v))

26
27
28

(define (scale-vect v s)
(make-vect (* s (xcor-vect v)) (* s (ycor-vect v)) ) )

29
30
31

(define (add-vect v1 v2)


(make-vect

32

(+ (xcor-vect v1) (xcor-vect v2))

33

(+ (ycor-vect v1) (ycor-vect v2)) ) )

34
35
36

(define (sub-vect v1 v2)


(make-vect

37

(- (xcor-vect v1) (xcor-vect v2))

38

(- (ycor-vect v1) (ycor-vect v2)) ) )

39
40

;; =======================================================

41

;; TESTS

42

;; =======================================================

43
44

(define v1 (make-vect

2))

45

(define v2 (make-vect

-4))

46
47

(prnvar "v1

" v1)

48

(prnvar "v2

" v2)

49

(prnvar "v1.x " (xcor-vect v1))

50

(prnvar "v1.y " (ycor-vect v1))

51

(prnvar "v1

52

(prnvar "v1+v2" (add-vect v1 v2))

53

(prnvar "v1-v2" (sub-vect v1 v2))

" (scale-vect v1 2))

54
55

;; *EOF*

46

## ./sicp_ch2_e2-46.scm
v1
v2
v1.x
v1.y
v1
v1+v2
v1-v2

2.3
2.3.1

:=
:=
:=
:=
:=
:=
:=

(1
(1
1
2
(2
(2
(0

. 2)
. -4)

. 4)
. -2)
. 6)

Symbolic Data
Quotation

Exercise 2.54. Two lists are said to be equal? if they contain equal elements arranged in the same order.
For example,

(equal? (this is a list) (this is a list))

is true, but

(equal? (this is a list) (this (is a) list))

is false. To be more precise, we can define equal? recursively in terms of

the basic eq? equality of symbols by saying that a and b are equal? if they are both symbols and the
symbols are eq?, or if they are both lists such that (car a) is equal? to (car b) and (cdr a) is equal? to (cdr
b). Using this idea, implement equal? as a procedure.

Comparing to structures using equals?:

(equals? a b) = f (a, b) =

if S (a) S (b)
?

a=b
if S (a) S (b)

f (aA , bA ) f (aD , bD ) if L (a) L (b)

47

(21)

where

L (a) L (b) = (S (a) S (b))


(22)

To show that all cases have been exhausted (23):

S (a) S (b) S (a) S (b) S (a) S (b) (S (a) S (b))


F

(23)

At this point, the recursive form is functional, but it is not expressed in tail-recursive form, and as such
is not subject to tail-call optimization. The following is a conversion to tail-recursive form:

(equals? a b) = f (a, b) = fk (a, b, >)

if S (a) S (b)


?
fk (a, b, p) = p a =
b
if S (a) S (b)

fk (aD , bD , fk (aA , bA , p)) otherwise

#!/usr/bin/csi -s

;; sicp_ch2_e2-54.scm

48

(24)

(24)

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 2.54. Two lists are said to be equal? if they contain equal

;;; elements arranged in the same order. For example,

10

;;;

11

;;; (equal? (this is a list) (this is a list))

12

;;;

13

;;; is true, but

14

;;;

15

;;; (equal? (this is a list) (this (is a) list))

16

;;;

17

;;; is false. To be more precise, we can define equal? recursively in terms of

18

;;; the basic eq? equality of symbols by saying that a and b are equal? if

19

;;; they are both symbols and the symbols are eq?, or if they are both lists

20

;;; such that (car a) is equal? to (car b) and (cdr a) is equal? to (cdr b).

21

;;; Using this idea, implement equal? as a procedure.

22
23

;; =======================================================

24

;; NOT TAIL-RECURSIVE

25

;; =======================================================

26
27

;;

28

;;

29

{ #f

if

s(a) and s(b)

;; f(a,b) = { a =?= b

if

s(a) xor s(b)

30

;;

if !( s(a) and s(b) )

31

;;

32

(define (my-equal-subopt? a b)

{ f(car(a),car(b)) ^ f(cdr(a),cdr(b))

33

(define (notlist? x) (not (list? x)))

34

(cond

35

;;

36

;; case: null(a) ^ null(b) ->

37

;;

38

( (and (null? a) (null? b))

#t

(null check)

#t )

39
40

;;

41

;; case: s(a) ^ s(b)

42

;;

->

a =?= b

49

( (and (notlist?

43

a) (notlist?

(eq? a b) )

44
45

;;

46

;; case: s(a) xor s(b)

47

;;

48

->

#f

(xor (notlist? a) (notlist? b))


#f )

49
50

;;

51

;; case: !( s(a)^s(b) )

52

;;

53

;;

54

;;

55

( else

->

f( cdr(a), cdr(b) )

i.e. (not (and (notlist? a) (notlist? b)))

(and (eq? (car a) (car b)) (my-equal-subopt? (cdr a) (cdr b))) )

56

57
58

b))

59
60

;; =======================================================

61

;; TAIL-RECURSIVE

62

;; =======================================================

63
64

;;

65

;;

66

{ #f

if

s(a) and s(b)

;; f(a,b,p=#t) = { p ^ a =?= b

if

s(a) xor s(b)

67

;;

if !( s(a) and s(b) )

68

;;

69

(define (my-equal? a b)

{ f(cdr(a), cdr(b), f(car(a),car(a),p))

70

(define (notlist? x) (not (list? x)))

71

(define (f a b p)

72

(cond

73

;;

74

;; case: null(a) ^ null(b) ->

75

;;

76

(null check)

(and (null? a) (null? b) )


#t )

77
78

;;

79

;; case: s(a) ^ s(b)

80

;;

81

82

#t

->

a =?= b

(and (notlist? a) (notlist? b))


(eq? a b) )

50

83

;;

84

;; case: s(a) xor s(b)

85

;;

86

#f

(xor (notlist? a) (notlist? b))


#f )

87
88

;;

89

;; case: !( s(a)^s(b) )

90

;;

91

( else

->

f( cdr(a), cdr(b) )

(f (cdr a) (cdr b) (f (car a) (car b) p) ) )

92

) ;; cond

93
94

95

(f a b #t) ;; <= base

96

->

;; <= recur

97
98

(bar)

99

(prn "intrinsic:")

100

(prn (equal? (this is a list) (this is a list))

101

(prn (equal? (this is a list) (this (is a) list))

102

(hr)

103

(prn "example 2-54: (not tail-recursive)")

104

(prn (my-equal-subopt? (this is a list) (this is a list))

105

(prn (my-equal-subopt? (this is a list) (this (is a) list)) )

106

; (hr)

107

; (prn "example 2-54: (tail-recursive)")

108

; (prn (my-equal? (this is a list) (this is a list))

109

; (prn (my-equal? (this is a list) (this (is a) list)) )

110

(bar)

111
112

;; *EOF*

## ./sicp_ch2_e2-54.scm
================================================================================
intrinsic:
#t
#f
-------------------------------------------------------------------------------example 2-54: (not tail-recursive)
#t
#f
================================================================================

Exercise 2.55. Eva Lu Ator types to the interpreter the expression (car abracadabra)
To her surprise, the interpreter prints back quote. Explain.
51

#!/usr/bin/csi -s

;; sicp_ch2_e2-55.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 2.55. Eva Lu Ator types to the interpreter the expression (car abracadabra)

;;; To her surprise, the interpreter prints back quote. Explain.

10
11

(bar)

12

(prn (car abracadabra) )

13

(hr)

14

(prn "Quote constructs a non-modifiable list, whose contents are the literal arguments to quote.")

15

(prn "The second quote is part of the literal quoted list.")

16

(prn "Car returns the first element of the list, which itself is quote.")

17

(bar)

18
19

;; *EOF*

## ./sicp_ch2_e2-55.scm
================================================================================
quote
-------------------------------------------------------------------------------Quote constructs a non-modifiable list, whose contents are the literal arguments to quote.
The second quote is part of the literal quoted list.
Car returns the first element of the list, which itself is quote.
================================================================================

2.3.2

Example: Symbolic Differentiation

Exercise 2.56. Show how to extend the basic differentiator to handle more kinds of expressions. For instance,
implement the differentiation rule
d (un )
u
= nu1
u
x

#!/usr/bin/csi -s

;; sicp_ch2_e2-56.scm

;; Mac Radigan

52

(24)

4
5

(load "../library/util.scm")

(import util)

7
8

;;; Exercise 2.56.

;;; kinds of expressions. For instance, implement the differentiation rule

10

;;;

11

;;;

d(u^n)

12

;;;

------

13

;;;

dx

14

;;;

Show how to extend the basic differentiator to handle more

du
=

nu^-1 -dx

15
16
17
18

(define (deriv exp var)


(cond ((number? exp) 0)
((variable? exp)
(if (same-variable? exp var) 1 0))

19
20

((sum? exp)
(make-sum (deriv (addend exp) var)

21

(deriv (augend exp) var)))

22
23

((product? exp)
(make-sum

24

(make-product (multiplier exp)

25

(deriv (multiplicand exp) var))

26

(make-product (deriv (multiplier exp) var)

27

(multiplicand exp))))

28
29

30

d(u^n)

31

------

32

dx

33

34

((exponent? exp)

35
36

39
40

nu^-1 -dx

(make-product
(make-product (power exp)
(make-exponent (base exp) (- (power exp) 1)))

37
38

du

(deriv (base exp) var)))


(else
(error "unknown expression type -- DERIV" exp))))

41
42

(define (variable? x) (symbol? x))

43

53

44
45

(define (same-variable? v1 v2)


(and (variable? v1) (variable? v2) (eq? v1 v2)))

46
47

(define (make-sum a1 a2) (list + a1 a2))

48
49

(define (=number? exp num) (and (number? exp) (= exp num)))

50
51

(define (make-product m1 m2) (list * m1 m2))

52
53

(define (make-exponent b p)

54

(cond ((=number? p 0) 1)

55

((=number? p 1) b)

56

(else (^ b p))))

57
58

(define (exponent? x) (eq? (car x) ^))

59
60

(define (base x) (cadr x))

61

(define (power x) (caddr x))

62
63

(define (sum? x) (and (pair? x) (eq? (car x) +)))

64
65

(define (addend s) (cadr s))

66
67

(define (augend s) (caddr s))

68
69
70

(define (product? x)
(and (pair? x) (eq? (car x) *)))

71
72

(define (multiplier p) (cadr p))

73
74

(define (multiplicand p) (caddr p))

75
76

(bar)

77

(prnvar "d/dx (2x)^4" (deriv (^ (* 2 x) 4) x))

78

(bar)

79
80

;; *EOF*

54

## ./sicp_ch2_e2-56.scm
================================================================================
d/dx (2x)^4 := (* (* 4 ((quote ^) b p)) (+ (* 2 1) (* 0 x)))
================================================================================

2.3.3

Example: Representing Sets

2.3.4

Example: Huffman Encoding Trees

2.4

Multiple Representations for Abstract Data

2.4.1

Representations for Complex Numbers

2.4.2

Tagged data

2.4.3

Data-Directed Programming and Additivity

2.5

Systems with Generic Operations

2.5.1

Generic Arithmetic Operations

2.5.2

Combining Data of Different Types

2.5.3

Example: Symbolic Algebra

55

Modularity, Objects, and State

3.1

Assignment and Local State

3.1.1

Local State Variables

3.1.2

The Benefits of Introducing Assignment

3.1.3

The Costs of Introducing Assignment

3.2

The Environment Model of Evaluation

3.2.1

The Rules for Evaluation

3.2.2

Applying Simple Procedures

3.2.3

Frames as the Repository of Local State

3.2.4

Internal Definitions

3.3

Modeling with Mutable Data

3.3.1

Mutable List Structure

3.3.2

Representing Queues

3.3.3

Representing Tables

3.3.4

A Simulator for Digital Circuits

3.3.5

Propagation of Constraints

3.4

Concurrency: Time Is of the Essence

3.4.1

The Nature of Time in Concurrent Systems

3.4.2

Mechanisms for Controlling Concurrency

3.5
3.5.1

Streams
Streams Are Delayed Lists

Exercise 3.50. Complete the following definition, which generalizes stream-map to allow procedures that
take multiple arguments, analogous to map in section 2.2.3, footnote 12.
(define (stream-map proc . argstreams)

56

(if (<??> (car argstreams))


the-empty-stream
(<??>
(apply proc (map <??> argstreams))
(apply stream-map
(cons proc (map <??> argstreams))))))

#!/usr/bin/csi -s

;; sicp_ch3_e3-50.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

(use sicp sicp-eval sicp-eval-anal sicp-streams)

(load "./ch3support.scm")

10

(load "./ch3.scm")

11
12

;;; Exercise 3.50.

Complete the following definition, which generalizes stream-map

13

;;; to allow procedures that take multiple arguments, analogous to map in

14

;;; section 2.2.3, footnote 12.

15
16

;;;

(define (stream-map proc . argstreams)

17

;;;

18

;;;

the-empty-stream

19

;;;

(<??>

20

;;;

(apply proc (map <??> argstreams))

21

;;;

(apply stream-map

22

;;;

(if (<??> (car argstreams))

(cons proc (map <??> argstreams))))))

23
24
25

(define (stream-map proc . argstreams)


(if (stream-null? (car argstreams))

26

the-empty-stream

27

(cons-stream

28

(apply proc (map car argstreams))

29

(apply stream-map

30

(cons proc (map stream-cdr argstreams))))))

31
32

;;; NB Error: unbound variable: get-new-pair

57

33

;;; (constructor for the empty list)

34
35

;; *EOF*

3.5.2

Infinite Streams

3.5.3

Exploiting the Stream Paradigm

3.5.4

Streams and Delayed Evaluation

3.5.5

Modularity of Functional Programs and Modularity of Objects

58

Metalinguistic Abstraction

#!/usr/bin/csi -s

;; run-query.scm

;; Mac Radigan

4
5

(use sicp sicp-eval sicp-eval-anal sicp-streams)

(load "./ch4-query.scm")

(define false #f)

(define true #t)

(initialize-data-base microshaft-data-base)

10

(query-driver-loop)

11
12

;; *EOF*

59

4.1

The Metacircular Evaluator

4.1.1

The Core of the Evaluator

4.1.2

Representing Expressions

4.1.3

Evaluator Data Structures

4.1.4

Running the Evaluator as a Program

4.1.5

Data as Programs

4.1.6

Internal Definitions

4.1.7

Separating Syntactic Analysis from Execution

4.2

Variations on a Scheme Lazy Evaluation

4.2.1

Normal Order and Applicative Order

4.2.2

An Interpreter with Lazy Evaluation

4.2.3

Streams as Lazy Lists

4.3

Variations on a Scheme Nondeterministic Computing

4.3.1

Amb and Search

4.3.2

Examples of Nondeterministic Programs

4.3.3

Implementing the Amb Evaluator

4.4

Logic Programming

An excellent discussion of logic programming can be found in chapter 19 of Paul Grahams On Lisp [2].

4.4.1

Deductive Information Retrieval

Exercise 4.55. Give simple queries that retrieve the following information from the data base:
(a) all people supervised by Ben Bitdiddle;
(b) the names and jobs of all people in the accounting division;
(c) the names and addresses of all people who live in Slumerville.

60

#!/usr/bin/csi -s

;; sicp_ch4_e4-55.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

(use sicp sicp-eval sicp-eval-anal sicp-streams)

(load "./ch4-query.scm")

10

(define false #f)

11

(define true #t)

12
13

(initialize-data-base microshaft-data-base)

14
15

;;; Exercise 4.55.

Give simple queries that retrieve the following information from the data base:

16

;;;

a. all people supervised by Ben Bitdiddle;

17

;;;

b. the names and jobs of all people in the accounting division;

18

;;;

c. the names and addresses of all people who live in Slumerville.

19
20

;; =======================================================

21

;; QUERY PROCESSOR

22

;; =======================================================

23
24
25
26

(define (eval-query query)


(let ((q (query-syntax-process query)))
(cond ((assertion-to-be-added? q)

27

(add-rule-or-assertion! (add-assertion-body q))

28

(newline)

29

(display "Assertion added to data base.")

30

31

(else

32

(newline)

33

(display output-prompt)

34

;; [extra newline at end] (announce-output output-prompt)

35

(display-stream

36
37
38

(stream-map
(lambda (frame)
(instantiate q

39

frame

40

(lambda (v f)

61

(contract-question-mark v))))

41

(qeval q (singleton-stream ()))))

42

))))

43
44
45

;; =======================================================

46

;; a. all people supervised by Ben Bitdiddle:

47

;; =======================================================

48
49

(define query-a
(supervisor ?person (Bitdiddle Ben)) )

50
51

;; =======================================================

52

;; b. the names and jobs of all people in the accounting division;

53

;; =======================================================

54
55

(define query-b
(job ?person (accounting . ?title)) )

56
57

;; =======================================================

58

;; c. the names and addresses of all people who live in Slumerville.

59

;; =======================================================

60

(define query-c (address ?person (Slumerville . ?address)) )

61
62

;; =======================================================

63

;; TESTS

64

;; =======================================================

65
66

(bar)

67

(prn "Query A. all people supervised by Ben Bitdiddle:")

68

(eval-query query-a) (br) (hr)

69

(prn "Query B. the names and jobs of all people in the accounting division:")

70

(eval-query query-b) (br) (hr)

71

(prn "Query C. the names and addresses of all people who live in Slumerville:")

72

(eval-query query-c) (br)

73

(bar)

74
75

;; *EOF*

62

## ./sicp_ch4_e4-55.scm
================================================================================
Query A. all people supervised by Ben Bitdiddle:
;;; Query results:
(supervisor (Tweakit Lem E) (Bitdiddle Ben))
(supervisor (Fect Cy D) (Bitdiddle Ben))
(supervisor (Hacker Alyssa P) (Bitdiddle Ben))
-------------------------------------------------------------------------------Query B. the names and jobs of all people in the accounting division:
;;; Query results:
(job (Cratchet Robert) (accounting scrivener))
(job (Scrooge Eben) (accounting chief accountant))
-------------------------------------------------------------------------------Query C. the names and addresses of all people who live in Slumerville:
;;; Query results:
(address (Aull DeWitt) (Slumerville (Onion Square) 5))
(address (Reasoner Louis) (Slumerville (Pine Tree Road) 80))
(address (Bitdiddle Ben) (Slumerville (Ridge Road) 10))
================================================================================

Exercise 4.56. Formulate compound queries that retrieve the following information:
(a) the names of all people who are supervised by Ben Bitdiddle, together with their addresses;
(b) all people whose salary is less than Ben Bitdiddles, together with their salary and Ben Bitdiddles salary;
(c) all people who are supervised by someone who is not in the computer division, together with the supervisors name and job.

#!/usr/bin/csi -s

;; sicp_ch4_e4-56.scm

;; Mac Radigan

4
5

(load "../library/util.scm")

(import util)

7
8

(use sicp sicp-eval sicp-eval-anal sicp-streams)

(load "./ch4-query.scm")

10

(define false #f)

11

(define true #t)

12
13

(initialize-data-base microshaft-data-base)

14
15

;;; Exercise 4.56.

Formulate compound queries that retrieve the following information:

63

16

;;;

a. the names of all people who are supervised by Ben Bitdiddle, together with their addresses;

17

;;;

b. all people whose salary is less than Ben Bitdiddles, together with their salary and Ben

,
18

;;;
,

Bitdiddles salary;
c. all people who are supervised by someone who is not in the computer division, together with
the supervisors name and job.

19
20

;; =======================================================

21

;; QUERY PROCESSOR

22

;; =======================================================

23

(define (eval-query query)

24

(let ((q (query-syntax-process query)))

25

(cond ((assertion-to-be-added? q)

26
27

(add-rule-or-assertion! (add-assertion-body q))

28

(newline)

29

(display "Assertion added to data base.")

30

)
(else

31
32

(newline)

33

(display output-prompt)

34

;; [extra newline at end] (announce-output output-prompt)

35

(display-stream
(stream-map

36

(lambda (frame)

37

(instantiate q

38
39

frame

40

(lambda (v f)
(contract-question-mark v))))

41

(qeval q (singleton-stream ()))))

42

))))

43
44
45

;; =======================================================

46

;; a. the names of all people who are supervised by

47

;;

48

;; =======================================================

49
50
51
52
53

Ben Bitdiddle, together with their addresses

(define query-a
(and (supervisor (Bitdiddle Ben) ?person)
(address ?person ?address)
) ; conjunction
) ; query A

64

54
55

;; =======================================================

56

;; b. all people whose salary is less than Ben Bitdiddles,

57

;;

58

;; =======================================================

together with their salary and Ben Bitdiddles salary

59
60

;;; TODO

61

(define query-b

62

(and (salary (Bitdiddle Ben) ?max-salary)

63

(salary ?person ?salary)

64

) ; conjunction

65

) ; query B

66
67
68

; (define query-b

69

70

(salary ?person ?salary)

71

(lisp-value < ?salary ?max-salary)

72

73

; ) ; query B

74

75

;; =======================================================

76

;; c. all people who are supervised by someone who is not

77

;;

in the computer division, together with the

78

;;

supervisors name and job.

79

;; =======================================================

80

(and (salary (Bitdiddle Ben) ?max-salary)

) ; conjunction

(define query-c
(and (supervisor ?supervisor ?person)

81
82

(not (job ?supervisor (computer . ?supervisor-title)))

83

(job ?supervisor ?supervisor-job)


) ; conjunction

84
85

) ; query C

86
87

;; =======================================================

88

;; TESTS

89

;; =======================================================

90
91

(bar)

92

(prn "Query A. the names of all people who are supervised by Ben Bitdiddle, together with their
,

addresses")

65

93

(eval-query query-a) (br) (hr)

94

(prn "[TODO] Query B. all people whose salary is less than Ben Bitdiddles, together with their salary
,

and Ben Bitdiddles salary")

95

(eval-query query-b) (br) (hr)

96

(prn "Query C. all people who are supervised by someone who is not in the computer division, together
,

with the supervisors name and job.")

97

(eval-query query-c) (br)

98

(bar)

99
100

;; *EOF*

## ./sicp_ch4_e4-56.scm
================================================================================
Query A. the names of all people who are supervised by Ben Bitdiddle, together with their addresses
;;; Query results:
(and (supervisor (Bitdiddle Ben) (Warbucks Oliver)) (address (Warbucks Oliver) (Swellesley (Top Heap
,
Road))))
-------------------------------------------------------------------------------[TODO] Query B. all people whose salary is less than Ben Bitdiddles, together with their salary and Ben
,
Bitdiddles salary
;;; Query results:
(and (salary (Bitdiddle Ben) 60000) (salary (Aull DeWitt) 25000))
(and (salary (Bitdiddle Ben) 60000) (salary (Cratchet Robert) 18000))
(and (salary (Bitdiddle Ben) 60000) (salary (Scrooge Eben) 75000))
(and (salary (Bitdiddle Ben) 60000) (salary (Warbucks Oliver) 150000))
(and (salary (Bitdiddle Ben) 60000) (salary (Reasoner Louis) 30000))
(and (salary (Bitdiddle Ben) 60000) (salary (Tweakit Lem E) 25000))
(and (salary (Bitdiddle Ben) 60000) (salary (Fect Cy D) 35000))
(and (salary (Bitdiddle Ben) 60000) (salary (Hacker Alyssa P) 40000))
(and (salary (Bitdiddle Ben) 60000) (salary (Bitdiddle Ben) 60000))
-------------------------------------------------------------------------------Query C. all people who are supervised by someone who is not in the computer division, together with the
,
supervisors name and job.
;;; Query results:
(and (supervisor (Aull DeWitt) (Warbucks Oliver)) (not (job (Aull DeWitt) (computer . ?supervisor-title)))
,
(job (Aull DeWitt) (administration secretary)))
(and (supervisor (Cratchet Robert) (Scrooge Eben)) (not (job (Cratchet Robert) (computer .
,
?supervisor-title))) (job (Cratchet Robert) (accounting scrivener)))
(and (supervisor (Scrooge Eben) (Warbucks Oliver)) (not (job (Scrooge Eben) (computer .
,
?supervisor-title))) (job (Scrooge Eben) (accounting chief accountant)))
================================================================================

66

4.4.2

How the Query System Works

4.4.3

Is Logic Programming Mathematical Logic?

4.4.4

Implementing the Query System

67

68

5
5.1

Computing with Register Machines


Designing Register Machines

5.1.1

A Language for Describing Register Machines

5.1.2

Abstraction in Machine Design

5.1.3

Subroutines

5.1.4

Using a Stack to Implement Recursion

5.1.5

Instruction Summary

5.2

A Register-Machine Simulator

5.2.1

The Machine Model

5.2.2

The Assembler

5.2.3

Generating Execution Procedures for Instructions

5.2.4

Monitoring Machine Performance

5.3

Storage Allocation and Garbage Collection

5.3.1

Memory as Vectors

5.3.2

Maintaining the Illusion of Infinite Memory

5.4

The Explicit-Control Evaluator

5.4.1

The Core of the Explicit-Control Evaluator

5.4.2

Sequence Evaluation and Tail Recursion

5.4.3

Conditionals, Assignments, and Definitions

5.4.4

Running the Evaluator

5.5

Compilation

5.5.1

Structure of the Compiler

5.5.2

Compiling Expressions

5.5.3

Compiling Combinations

5.5.4

Combining Instruction Sequences

5.5.5

An Example of Compiled Code

5.5.6

Lexical Addressing

69

Appendix A: Modules

6.1

util.scm

#!/usr/bin/csi -s

;; util.scm

;; Mac Radigan

4
5

(module util (

bind

bar

bin

br

10

but-last

11

ck

12

compose

13

dec

14

dotprod

15

flatmap

16

fmt

17

hr

18

hex

19

inc

20

my-iota

21

join

22

kron-comb

23

lfsr

24

mat-*

25

mat-col

26

mat-row

27

mod

28

my-last

29

nth

30

oct

31

permute

32

pr

33

prn

34

prnvar

35

my-reverse

36

range

70

37

rotate-right

38

rotate-left

39

rotate

40

square

41

sum

42

xor

43

44

Y-normal

45

Y2

46

yeild

47

48

(import scheme chicken)

49

(use extras)

50

(use srfi-1)

51
52

;;; debug, formatted printing, and assertions

53

(define (br)

54

(format #t "~%"))

55
56
57

(define (pr x)
(format #t "~a" x))

58
59
60

(define (fmt s x)
(format #t s x))

61
62
63

(define (prn x)
(format #t "~a~%" x))

64
65
66

(define (prnvar name value)


(format #t "~a := ~a~%" name value))

67
68
69

(define (ck name pred? value expect)


(cond
( (not (pred? value expect)) (format #t "~a = ~a

70
71

72

(assert (pred? value expect))

73

(format #t "~a = ~a

74

; ok: expected ~a~%" name value expect)

) ; ck

75
76

; fail expected ~a~%" name value expect) )

;;; numeric formatting

71

77

(define (hex x)

(format #t "~x~%" x))

78

(define (bin x)

(format #t "~b~%" x))

79

(define (oct x)

(format #t "~o~%" x))

80
81

;;; delimiters

82

(define (bar)

(format #t "~a~%" (make-string 80 #\=)))

83

(define (hr)

(format #t "~a~%" (make-string 80 #\-)))

84
85

;;; returns the nth element of list x

86

(define (nth x n)

87

(if (= n 1)

88

(car x)

89

(nth (cdr x) (- n 1))


) ; if last iter

90
91

) ; nth

92
93

;;; returns the inner product <u,v>

94

(define (dotprod u v)
(apply + (map * u v))

95
96

97
98

;;; returns x mod n

99

(define (mod x n)
(- x (* n (floor (/ x n))))

100
101

102
103

;;; the permutation x by p

104

(define (permute x p)
(map (lambda (pk) (nth x pk)) p)

105
106

107
108

;;; circular shift (left) of x by n

109

(define (rotate-left x n)

110

(if (< n 1)

111

112

(rotate-left (append (cdr x) (list (car x))) (- n 1))

113
114

) ; if last iter
) ; rotate-left

115
116

;;; circular shift (right) of x by n

72

117

(define (rotate-right x n)
(if (< n 1)

118
119

120

(rotate-right

121

(append (list (my-last x)) (but-last x))

122

(- n 1)
) ; call

123

) ; if last iter

124
125

) ; rotate-right

126
127

;;; circular shift of x by n

128

(define (rotate x n)
(cond

129
130

((= n 0) x)

131

((> n 0) (rotate-right x n))

132

((< n 0) (rotate-left x (abs n)))


)

133
134

135
136

;;; return all but last element in list

137

(define (but-last x)
(if (null? x)

138
139

(list)

140

(if (null? (cdr x))

141

(list)

142

(cons (car x) (but-last (cdr x)))


) ; end if list contains only one element

143

) ; end if list null

144
145

146
147

;;; return the last element in list

148

(define (my-last x)
(if (null? x)

149
150

#f

151

(if (null? (cdr x))

152

(car x)

153

(my-last (cdr x))


) ; end if list contains only one element

154

) ; end if list null

155
156

73

157
158

;; composition

159

(define ((compose f g) x) (f (g x)))

160
161

;; my-reverse

162

(define (my-reverse x)
(if (null? x)

163
164

(list)

165

(append (my-reverse (cdr x)) (list (car x)))


)

166
167

168
169

;; Linear Feedback Shift Register (LFSR)

170

;;

given initial state x[k-1] and coefficients a

171

;;

return next state x[k]

172

(define (lfsr x a)
(append (list (dotprod x a)) (cdr (rotate x +1)) ) ; next state x[k]

173
174

) ; lfsr

175
176

;; matrix multiplication of column-major Iverson matrices

177

(define (mat-* A dimA B dimB)


(let (

178
179

; A_mxn * B_nxk = C_nxk

180

(M_rows (cadr dimA) ) ; M_rows

181

(N_cols (cadr dimB) ) ; N_cols

182

) ; local bindings

183

(map (lambda (rc)


(dotprod (mat-row A dimA (car rc)) (mat-col B dimB (cadr rc)) )

184
185

186

(kron-comb (my-iota N_cols) (my-iota M_rows))


)

187
188

) ; let

189

) ; mat-*

190
191

;; selects the kth column from a column-major Iverson matrix

192

;;

193

(define (mat-col A dim k)

194

NB:

dim is a pair ( M_rows , N_cols )

(let (

195

(start

) ; start

:= kth column

196

(stride (cadr dim) ) ; stride := N_cols

74

197

(M_rows (car dim)

) ; M_rows

198

(N_cols (cadr dim) ) ; N_cols

199

) ; local bindings

200

(choose A (range start stride M_rows))

201

) ; let

202

) ; mat-col

203
204

;; selects the kth column from a column-major Iverson matrix

205

;;

206

(define (mat-row A dim k)

NB:

dim is a pair ( M_rows , N_cols )

(let (

207
208

(start

(* k (cadr dim))

) ; start

209

(stride 1

) ; stride := 1

210

(M_rows (car dim)

) ; M_rows

211

(N_cols (cadr dim)

) ; N_cols

212

) ; local bindings

213

(choose A (range start stride N_cols))

214

) ; let

215

) ; mat-col

:= (kth row -1) * M_rows

216
217

;; flatmap (map flattened by one level)

218

(define (flatmap f x)
(apply append (map f x))

219
220

) ; flatmap

221
222

;; Kroneker combination of vectors a and b

223

(define (kron-comb a b)
(flatmap (lambda (ak) (map (lambda (bk) (list ak bk)) a)) b)

224
225

) ; kron-comb

226
227

;; returns a list with elements of x taken from positions ns

228

(define (choose x ns)


(map (lambda (k) (list-ref x k)) ns )

229
230

231
232

;; range sequence generator

233

(define (range start step n)


(range-iter () start step n)

234
235

236

75

237

;; Iversons iota: zero-based sequence of integers from 0..N

238

(define (my-iota n)
(range 0 1 n)

239
240

241
242

;; local scope: range sequence generator helper

243

(define (range-iter x val step n)


(if (< n 1)

244
245

246

(range-iter (append x (list val)) (+ val step) step (- n 1) ) ; x << val + step
)

247
248

249
250

;; exclusive or

251

(define (xor a b)
(or (and (not a) b) (and a (not b)))

252
253

254
255

;; square, sum, inc, and dec

256

(define (square x) (* x x))

257

(define (sum x) (apply + x) )

258

(define (inc x) (+ x 1))

259

(define (dec x) (- x 1))

260
261

;;; data transformations: bind, join, yeild

262

(define (bind f x) (join (map f x)))

263

(define (join x) (apply append () x))

264

(define yeild list)

265
266

;; Y combiner

267

;;

268

(define Y

strict-order

(lambda (f)

269

((lambda (x) (x x))

270

(lambda (x) (f (lambda (y) ((x x) y)))))))

271
272

;;

273

(define (Y-normal f)

274
275
276

normal-order

((lambda (x) (x x))


(lambda (x) (f (x x)))))
(define Y2

76

277

(lambda (h)
(lambda args (apply (h (Y h)) args))))

278
279
280
281

) ; module util

282
283

;; hello.scm

284
285

;; *EOF*

77

Appendix B: Installation Notes

7.1

Chicken Scheme

#!/bin/bash

## apt-install.sh

## Mac Radigan

apt install chicken-bin -y

## *EOF*

#!/bin/bash

## yum-install.sh

## Mac Radigan

yum -y install chicken

## *EOF*

#!/bin/bash

## brew-install.sh

## Mac Radigan

brew install chicken

## *EOF*

#!/bin/bash

## chicken-install.sh

## Mac Radigan

chicken-install sicp

# *EOF*

78

8
8.1

Appendix C: Notation
Membership
S (x) , x SYMBOL

(24)

L (x) , x LIST
(25)

8.2

Symbols
> , #t

(26)

, #f
(27)

8.3

Access
xA , (car x)

(28)

xD , (cdr x)
(29)

79

8.4

Equality
?

x = y , (eq? x y)
(30)

8.5

Logic
x , (not x)

(31)

x y , (and x y)
(32)

x y , (or x y)
(33)

x y , (x y) (x y) = (or (and (not x) (y)) (and (x) (not y)))


(34)

80

Appendix D: Y-Combinator

9.1

Introduction

Description of the Y Combinator based on Mike Mvaniers blog post [?]. see http://mvanier.livejournal.com/2897.html

9.2

Cannonical Expression

Currys Y Combinator [3] is defined as:

Y = f. (x.f (xx)) (x.f (xx))

(35)

When applied to a function g, the expansion follows [3]

Yg = (f. (x.f (xx)) (x.f (xx))) g


= (x.g (xx)) (x.g (xx))
(36)
= g ((x.g (xx)) (x.g (xx)))
= g (Yg)

9.3

Connonical Form in Scheme

Direct implementation of the above expression for the Y Combinator will not terminate during applicative
order [?].

9.3.1

Strict Scheme (Chicken)

Chicken scheme is a strict scheme, and evaluates in applicative order.


1

#!/usr/bin/csi -s

;; y-combinator.scm

;; Mac Radigan

;;

;; copied from http://mvanier.livejournal.com/2897.html

6
7

(load "../library/util.scm")

(import util)

9
10
11

;;; Eliminating (most) explicit recursion (lazy version)

81

12

(define Y

13

(lambda (f)

14

(f (Y f))))

15
16

(define almost-factorial

17

(lambda (f)

18

(lambda (n)

19

(if (= n 0)

20
21

22

(* n (f (- n 1)))))))

23

(define factorial (Y almost-factorial))

24
25

(prn (factorial 6)) ; infinite loop

26
27
28

;; *EOF*

9.3.2

Using Lazy Evaluation (Racket #lang lazy)

This will work in a lazy language, as shown using the lazy extension in Racket.
1

#!/usr/bin/racket

;; y-combinator.scm

;; Mac Radigan

;;

;; copied from http://mvanier.livejournal.com/2897.html

6
7

#lang lazy

8
9

;;; Eliminating (most) explicit recursion (lazy version)

10
11
12
13

(define Y
(lambda (f)
(f (Y f))))

14
15
16
17
18
19

(define almost-factorial
(lambda (f)
(lambda (n)
(if (= n 0)
1

82

(* n (f (- n 1)))))))

20
21

(define factorial (Y almost-factorial))

22
23

(println (factorial 6)) ; 720

24
25
26

;; *EOF*

## ./y-combinator.rkt-lazy
720

9.4

Normal Order Y Combinator

The Normal Order Y Combinator will not terminate during applicative order [?].
9.4.1

Strict Scheme (Chicken)

#!/usr/bin/csi -s

;; y-combinator-normal.scm

;; Mac Radigan

;;

;; copied from http://mvanier.livejournal.com/2897.html

6
7

(load "../library/util.scm")

(import util)

9
10
11

;;; The lazy (normal-order) Y combinator

12
13
14
15
16

(define Y
(lambda (f)
((lambda (x) (f (x x)))
(lambda (x) (f (x x))))))

17
18
19
20
21

(define almost-factorial
(lambda (f)
(lambda (n)
(if (= n 0)

22

23

(* n (f (- n 1)))))))

83

24

(define factorial (Y almost-factorial))

25
26

(prn (factorial 6)) ; infinite loop

27
28
29

;; *EOF*

9.4.2

Using Strict Evaluation (Racket)

#!/usr/bin/racket

;; y-combinator-normal.scm

;; Mac Radigan

;;

;; copied from http://mvanier.livejournal.com/2897.html

6
7

#lang lazy

8
9

;;; The lazy (normal-order) Y combinator

10
11

(define Y
(lambda (f)

12

((lambda (x) (f (x x)))

13

(lambda (x) (f (x x))))))

14
15
16

(define almost-factorial
(lambda (f)

17

(lambda (n)

18

(if (= n 0)

19
20

21

(* n (f (- n 1)))))))

22
23

(define factorial (Y almost-factorial))

24
25

(println (factorial 6)) ; 720

26
27

;; *EOF*

9.4.3

Using Lazy Evaluation (Racket #lang lazy)

However, it will work under lazy evaluation.

84

#!/usr/bin/racket

;; y-combinator-normal.scm

;; Mac Radigan

;;

;; copied from http://mvanier.livejournal.com/2897.html

#lang lazy

7
8

;;; The lazy (normal-order) Y combinator

9
10

(define Y

11

(lambda (f)

12

((lambda (x) (f (x x)))

13

(lambda (x) (f (x x))))))

14
15

(define almost-factorial

16

(lambda (f)

17

(lambda (n)

18

(if (= n 0)

19
20

21

(* n (f (- n 1)))))))

22

(define factorial (Y almost-factorial))

23
24

(println (factorial 6)) ; 720

25
26
27

;; *EOF*

## ./y-combinator-normal.rkt-lazy
720

9.5

Strict (Applicative-Order) Y Combinator

The Strict (Applicative-Order) Y Combinator can be used with both applicative order and lazy evaluation
[?].

9.5.1

Strict Scheme (Chicken)

85

#!/usr/bin/csi -s

;; y-combinator-struct.scm

;; Mac Radigan

;;

;; copied from http://mvanier.livejournal.com/2897.html

6
7

(load "../library/util.scm")

(import util)

9
10
11

;;; The strict (applicative-order) Y combinator

12
13
14
15
16

(define Y
(lambda (f)
((lambda (x) (x x))
(lambda (x) (f (lambda (y) ((x x) y)))))))

17
18
19
20

(define almost-factorial
(lambda (f)
(lambda (n)
(if (= n 0)

21
22

23

(* n (f (- n 1)))))))

24
25
26
27

(define (part-factorial self)


(let ((f (lambda (y) ((self self) y))))
(lambda (n)
(if (= n 0)

28
29

30

(* n (f (- n 1)))))))

31
32

(define factorial (Y almost-factorial))

33
34

(prn (factorial 6)) ; 720

35
36

;; *EOF*

## ./y-combinator-strict.scm

86

9.5.2

Using Strict Evaluation (Racket)

#!/usr/bin/racket

;; y-combinator-struct.scm

;; Mac Radigan

;;

;; copied from http://mvanier.livejournal.com/2897.html

#lang racket

7
8

;;; The strict (applicative-order) Y combinator

9
10

(define Y

11

(lambda (f)

12

((lambda (x) (x x))

13

(lambda (x) (f (lambda (y) ((x x) y)))))))

14
15

(define almost-factorial

16

(lambda (f)

17

(lambda (n)

18

(if (= n 0)

19
20

21

(* n (f (- n 1)))))))

22

(define (part-factorial self)

23

(let ((f (lambda (y) ((self self) y))))

24

(lambda (n)

25

(if (= n 0)

26
27

28

(* n (f (- n 1)))))))

29

(define factorial (Y almost-factorial))

30
31

(println (factorial 6)) ; 720

32
33
34

;; *EOF*

## ./y-combinator-strict.rkt
720

87

9.5.3

Using Lazy Evaluation (Racket #lang lazy)

#!/usr/bin/racket

;; y-combinator-struct.scm

;; Mac Radigan

;;

;; copied from http://mvanier.livejournal.com/2897.html

#lang lazy

7
8

;;; The strict (applicative-order) Y combinator

9
10

(define Y

11

(lambda (f)

12

((lambda (x) (x x))

13

(lambda (x) (f (lambda (y) ((x x) y)))))))

14
15

(define almost-factorial

16

(lambda (f)

17

(lambda (n)

18

(if (= n 0)

19
20

21

(* n (f (- n 1)))))))

22

(define (part-factorial self)

23

(let ((f (lambda (y) ((self self) y))))

24

(lambda (n)

25

(if (= n 0)

26
27

28

(* n (f (- n 1)))))))

29

(define factorial (Y almost-factorial))

30
31

(println (factorial 6)) ; 720

32
33
34

;; *EOF*

## ./y-combinator-strict.rkt-lazy
720

88

References
[1] H. Abelson and G. J. Sussman, Structure and Interpretation of Computer Programs, 2nd Edition.
Cambridge, MA, USA: MIT Press, 1996.
[2] P. Graham, On LISP: Advanced Techniques for Common LISP. Upper Saddle River, NJ, USA: PrenticeHall, Inc., 1993.
[3] M. Mvanier, The y combinator (slight return) or how to succeed at recursion without really recursing,
http://mvanier.livejournal.com/2897.html, 2010.
[4] Wikipedia, Fixed-point combinator Wikipedia, the free encyclopedia, 2011, [Online; accessed
11-July-2016]. [Online]. Available: http://en.wikipedia.org/Fixed-point combinator
[5] J. Bender, Read scheme, 2009, [Online; accessed 11-July-2016]. [Online]. Available:

http:

//readscheme.org
[6] ,

Read scheme,

2009,

[Online;

accessed 11-July-2016]. [Online]. Available:

http:

//repository.readscheme.org/ftp
[7] K. E. Iverson, Notation as a tool of thought, 2006, [Online; accessed 11-July-2016]. [Online].
Available: http://www.eecg.toronto.edu/jzhu/csc326/readings/iverson.pdf
[8] P. Michaux,

peter.michaux.ca,

2006,

[Online;

accessed 11-July-2016]. [Online]. Available:

http://peter.michaux.ca
[9] , bootstrap-scheme, 2010, [Online;

accessed 11-July-2016]. [Online]. Available:

https:

//github.com/petermichaux/bootstrap-scheme
[10] H. G. Baker, Cons should not cons its arguments, part ii: Cheney on the m.t.a. SIGPLAN Not.,
vol. 30, no. 9, pp. 1720, Sep. 1995. [Online]. Available: http://doi.acm.org/10.1145/214448.214454
[11] J. A. Brzozowski, Derivatives of regular expressions, J. ACM, vol. 11, no. 4, pp. 481494, Oct. 1964.
[Online]. Available: http://doi.acm.org/10.1145/321239.321249
[12] B. Ford and M. F. Kaashoek, Packrat parsing: a practical linear-time algorithm with backtracking,
2002.
[13] G. L. Steele, Jr., Common LISP: The Language, (2nd Ed.).

Newton, MA, USA: Digital Press, 1990.

[14] J. A. Brzozowski, Derivatives of regular expressions, J. ACM, vol. 11, no. 4, pp. 481494, Oct. 1964.
[Online]. Available: http://doi.acm.org/10.1145/321239.321249
89

[15] P. Norvig, Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp, 1st ed.
San Francisco, CA, USA: Morgan Kaufmann Publishers Inc., 1992.

90

You might also like