let and let*

125
1 LET and LET*

Upload: others

Post on 27-Jan-2022

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: LET and LET*

1

LET and LET*

Page 2: LET and LET*

2

LET gives values to local variables for use in an expression.

Example: (let ((x (- 2 1)) (y 3) (z (* 2 4))) (+ x (* y z))) ⇒

Page 3: LET and LET*

3

LET gives values to local variables for use in an expression.

Example: (let ((x (- 2 1)) (y 3) (z (* 2 4))) (+ x (* y z))) ⇒ 25

Page 4: LET and LET*

4

LET gives values to local variables for use in an expression.

Example: (let ((x (- 2 1)) (y 3) (z (* 2 4))) (+ x (* y z))) ⇒ 25

This LET expression can be understood as meaning (+ x (* y z)) where x = (- 2 1), y = 3, z = (* 2 4)

Page 5: LET and LET*

5

LET gives values to local variables for use in an expression.

Example: (let ((x (- 2 1)) (y 3) (z (* 2 4))) (+ x (* y z))) ⇒ 25

This LET expression can be understood as meaning (+ x (* y z)) where x = (- 2 1), y = 3, z = (* 2 4)

The scope of the local variables introduced by a LET expression is confined to the body of the expression.

• To illustrate this, suppose we define a function as follows:

(defun g (x) (list (let ((x 10)) (* x x)) x))

Then the last x is the parameter x of g, which is unrelated to the local variable x of the LET!

Hence: (g 3) ⇒ (100 3)

Page 6: LET and LET*

6

LET gives values to local variables for use in an expression.

Example: (let ((x (- 2 1)) (y 3) (z (* 2 4))) (+ x (* y z))) ⇒ 25

This LET expression can be understood as meaning (+ x (* y z)) where x = (- 2 1), y = 3, z = (* 2 4)

The scope of the local variables introduced by a LET expression is confined to the body of the expression.

• To illustrate this, suppose we define a function as follows:

(defun g (x) (list (let ((x 10)) (* x x)) x))

Then this x is the parameter x of g, which is unrelated to the local variable x of the LET!

Hence: (g 3) ⇒ (100 3)

Page 7: LET and LET*

7

LET gives values to local variables for use in an expression.

Example: (let ((x (- 2 1)) (y 3) (z (* 2 4))) (+ x (* y z))) ⇒ 25

This LET expression can be understood as meaning (+ x (* y z)) where x = (- 2 1), y = 3, z = (* 2 4)

The scope of the local variables introduced by a LET expression is confined to the body of the expression.

• To illustrate this, suppose we define a function as follows:

(defun g (x) (list (let ((x 10)) (* x x)) x))

Then this x is the parameter x of g, which is unrelated to the local variable x of the LET!

Hence: (g 3) ⇒

Page 8: LET and LET*

8

LET gives values to local variables for use in an expression.

Example: (let ((x (- 2 1)) (y 3) (z (* 2 4))) (+ x (* y z))) ⇒ 25

This LET expression can be understood as meaning (+ x (* y z)) where x = (- 2 1), y = 3, z = (* 2 4)

The scope of the local variables introduced by a LET expression is confined to the body of the expression.

• To illustrate this, suppose we define a function as follows:

(defun g (x) (list (let ((x 10)) (* x x)) x))

Then this x is the parameter x of g, which is unrelated to the local variable x of the LET!

Hence: (g 3) ⇒ (100 3)

Page 9: LET and LET*

9

Examples from pp. 141 – 3 of Touretzky:

Page 10: LET and LET*

10

Examples from pp. 141 – 3 of Touretzky:

Page 11: LET and LET*

11

Examples from pp. 141 – 3 of Touretzky:

Page 12: LET and LET*

12

Examples from pp. 141 – 3 of Touretzky:

Page 13: LET and LET*

13

Examples from pp. 141 – 3 of Touretzky:

Page 14: LET and LET*

14

Examples from pp. 141 – 3 of Touretzky:

Page 15: LET and LET*

15

Examples from pp. 141 – 3 of Touretzky:

Page 16: LET and LET*

16

Examples from pp. 141 – 3 of Touretzky:

Page 17: LET and LET*

17

Examples from pp. 141 – 3 of Touretzky:

• These examples illustrate one reason we use LET (or LET*): To give meaningful names (e.g., sum, star, and co-star) to the values of certain expressions and so make code more readable. Another reason to use LET or LET* will be discussed later.

Page 18: LET and LET*

18

Evaluation of LET Forms

This is from p. 142 of Touretzky.

In functional programming, body consists of just one expression whose value will be returned as the value of the entire LET form.

• The expressions value-1, … , value-n are evaluated using the variable bindings that existed just before the LET expression.

• The local variables var-1, … , var-n will be given the values of the expressions value-1, … , value-n, but they are not visible when those expressions are being evaluated!

• Once the body expression has been evaluated, the n local variables cease to exist: var-1, … , var-n will then have the values, if any, that they had before the LET expression.

Page 19: LET and LET*

19

Evaluation of LET Forms

This is from p. 142 of Touretzky.

In functional programming, body consists of just one expression whose value will be returned as the value of the entire LET form.

• The expressions value-1, … , value-n are evaluated using the variable bindings that existed just before the LET expression.

• The local variables var-1, … , var-n will be given the values of the expressions value-1, … , value-n, but they are not visible when those expressions are being evaluated!

• Once the body expression has been evaluated, the n local variables cease to exist: var-1, … , var-n will then have the values, if any, that they had before the LET expression.

Page 20: LET and LET*

20

Evaluation of LET Forms

This is from p. 142 of Touretzky.

In functional programming, body consists of just one expression whose value will be returned as the value of the entire LET form.

• The expressions value-1, … , value-n are evaluated using the variable bindings that existed just before the LET expression.

• The local variables var-1, … , var-n will be given the values of the expressions value-1, … , value-n, but they are not visible when those expressions are being evaluated!

• Once the body expression has been evaluated, the n local variables cease to exist: var-1, … , var-n will then have the values, if any, that they had before the LET expression.

Page 21: LET and LET*

21

Evaluation of LET Forms

This is from p. 142 of Touretzky.

In functional programming, body consists of just one expression whose value will be returned as the value of the entire LET form.

• The expressions value-1, … , value-n are evaluated using the variable bindings that existed just before the LET expression.

• The local variables var-1, … , var-n will be given the values of the expressions value-1, … , value-n, but they are not visible when those expressions are being evaluated!

• Once the body expression has been evaluated, the n local variables cease to exist: var-1, … , var-n will then have the values, if any, that they had before the LET expression.

Page 22: LET and LET*

22

Evaluation of LET Forms

This is from p. 142 of Touretzky.

In functional programming, body consists of just one expression whose value will be returned as the value of the entire LET form.

• The expressions value-1, … , value-n are evaluated using the variable bindings that existed just before the LET expression.

• The local variables var-1, … , var-n will be given the values of the expressions value-1, … , value-n, but they are not visible when those expressions are being evaluated!

• Once the body expression has been evaluated, the n local variables cease to exist: var-1, … , var-n will then have the values, if any, that they had before the LET expression.

Page 23: LET and LET*

23

Evaluation of LET Forms

This is from p. 142 of Touretzky.

In functional programming, body consists of just one expression whose value will be returned as the value of the entire LET form.

• The expressions value-1, … , value-n are evaluated using the variable bindings that existed just before the LET expression.

• The local variables var-1, … , var-n will be given the values of the expressions value-1, … , value-n, but they are not visible when those expressions are being evaluated!

• Once the body expression has been evaluated, the n local variables cease to exist: var-1, … , var-n will then have the values, if any, that they had before the LET expression.

Page 24: LET and LET*

24

From p. 143 of Touretzky.

Page 25: LET and LET*

25

From p. 143 of Touretzky.

Page 26: LET and LET*

26

From p. 143 of Touretzky.

Page 27: LET and LET*

27

From p. 143 of Touretzky.

Page 28: LET and LET*

28

From p. 143 of Touretzky.

Page 29: LET and LET*

29

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ x ⇒ y ⇒ (+ (let ((a (sqrt x)) local a ⇒ (b (* x 2)) local b ⇒ (c (+ x y))) local c ⇒ (/ (+ a b c) w)) LET ⇒ x))

(g 3 4 7) ⇒

Page 30: LET and LET*

30

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) the LET's local a ⇒ (b (* x 2)) the LET's local b ⇒ (c (+ x y))) the LET's local c ⇒ (/ (+ a b c) w)) LET ⇒ x)) x ⇒

(g 3 4 7) ⇒

Page 31: LET and LET*

31

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) the LET's local a ⇒ (b (* x 2)) the LET's local b ⇒ (c (+ x y))) the LET's local c ⇒ (/ (+ a b c) w)) LET ⇒ x)) x ⇒

(g 3 4 7) ⇒

Page 32: LET and LET*

32

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) the LET's local a ⇒ 2 (b (* x 2)) the LET's local b ⇒ (c (+ x y))) the LET's local c ⇒ (/ (+ a b c) w)) LET ⇒ x)) x ⇒

(g 3 4 7) ⇒

Page 33: LET and LET*

33

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) the LET's local a ⇒ 2 (b (* x 2)) the LET's local b ⇒ 8 (c (+ x y))) the LET's local c ⇒ (/ (+ a b c) w)) LET ⇒ x)) x ⇒

(g 3 4 7) ⇒

Page 34: LET and LET*

34

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) the LET's local a ⇒ 2 (b (* x 2)) the LET's local b ⇒ 8 (c (+ x y))) the LET's local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ x)) x ⇒

(g 3 4 7) ⇒

Page 35: LET and LET*

35

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) the LET's local a ⇒ 2 (b (* x 2)) the LET's local b ⇒ 8 (c (+ x y))) the LET's local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒

(g 3 4 7) ⇒

Page 36: LET and LET*

36

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) the LET's local a ⇒ 2 (b (* x 2)) the LET's local b ⇒ 8 (c (+ x y))) the LET's local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒

Page 37: LET and LET*

37

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) the LET's local a ⇒ 2 (b (* x 2)) the LET's local b ⇒ 8 (c (+ x y))) the LET's local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 7+4 = 11

Page 38: LET and LET*

38

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) local a ⇒ 2 (b (* x 2)) local b ⇒ 8 (c (+ x y))) local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ x ⇒ y ⇒ (+ (let ((x (sqrt x)) local x ⇒ (y (* x 2)) local y ⇒ (z (+ x y))) local z ⇒ (/ (+ x y z) w)) LET ⇒ x)) x ⇒

(h 3 4 7) ⇒

Page 39: LET and LET*

39

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) local a ⇒ 2 (b (* x 2)) local b ⇒ 8 (c (+ x y))) local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ x ⇒ y ⇒ (+ (let ((x (sqrt x)) the LET's local x ⇒ (y (* x 2)) the LET's local y ⇒ (z (+ x y))) the LET's local z ⇒ (/ (+ x y z) w)) LET ⇒ x)) x ⇒

(h 3 4 7) ⇒

Page 40: LET and LET*

40

ther example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) local a ⇒ 2 (b (* x 2)) local b ⇒ 8 (c (+ x y))) local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ (y (* x 2)) the LET's local y ⇒ (z (+ x y))) the LET's local z ⇒ (/ (+ x y z) w)) LET ⇒ x)) x ⇒

(h 3 4 7) ⇒

Page 41: LET and LET*

41

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) local a ⇒ 2 (b (* x 2)) local b ⇒ 8 (c (+ x y))) local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ (z (+ x y))) the LET's local z ⇒ (/ (+ x y z) w)) LET ⇒ x)) x ⇒

(h 3 4 7) ⇒

Page 42: LET and LET*

42

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) local a ⇒ 2 (b (* x 2)) local b ⇒ 8 (c (+ x y))) local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ (/ (+ x y z) w)) LET ⇒ x)) x ⇒

(h 3 4 7) ⇒

Page 43: LET and LET*

43

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) local a ⇒ 2 (b (* x 2)) local b ⇒ 8 (c (+ x y))) local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ x)) x ⇒

(h 3 4 7) ⇒

Page 44: LET and LET*

44

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) local a ⇒ 2 (b (* x 2)) local b ⇒ 8 (c (+ x y))) local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒

(h 3 4 7) ⇒

Page 45: LET and LET*

45

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) local a ⇒ 2 (b (* x 2)) local b ⇒ 8 (c (+ x y))) local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒

Page 46: LET and LET*

46

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) local a ⇒ 2 (b (* x 2)) local b ⇒ 8 (c (+ x y))) local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 7+4 = 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11

Page 47: LET and LET*

47

Another example: Evaluation of (g 3 4 7):

(defun g (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((a (sqrt x)) the LET's local a ⇒ 2 (b (* x 2)) the LET's local b ⇒ 8 (c (+ x y))) the LET's local c ⇒ 11 (/ (+ a b c) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(g 3 4 7) ⇒ 7+4 = 11 A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11

Page 48: LET and LET*

48

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows: (my-helper-function expr1 … exprn)

Page 49: LET and LET*

49

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows:

Page 50: LET and LET*

50

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows: (my-helper-function expr1 … exprn)

For example,

Page 51: LET and LET*

51

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows: (my-helper-function expr1 … exprn)

For example, evaluation of (let ((a (sqrt x)) (b (* x 2)) (c (+ x y))) (/ (+ a b c) 5)) LET ⇒ is roughly equivalent to making a definition (defun my-helper-function (a b c) (/ (+ a b c) 5)) and then calling the function as follows:

Page 52: LET and LET*

52

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows: (my-helper-function expr1 … exprn)

For example, evaluation of (let ((a (sqrt x)) (b (* x 2)) (c (+ x y))) (/ (+ a b c) 5)) LET ⇒ is roughly equivalent to making a definition (defun my-helper-function (a b c) (/ (+ a b c) 5)) and then calling the function as follows:

Page 53: LET and LET*

53

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows: (my-helper-function expr1 … exprn)

For example, evaluation of (let ((a (sqrt x)) (b (* x 2)) (c (+ x y))) (/ (+ a b c) 5)) LET ⇒ is roughly equivalent to making a definition (defun my-helper-function (a b c) (/ (+ a b c) 5)) and then calling the function as follows: (my-helper-function (sqrt x) (* x 2) (+ x y))

Page 54: LET and LET*

54

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows: (my-helper-function expr1 … exprn)

Page 55: LET and LET*

55

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows: (my-helper-function expr1 … exprn) In fact (let ((x1 expr1) ⋮ (xn exprn)) body) is essentially equivalent to:

Page 56: LET and LET*

56

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows: (my-helper-function expr1 … exprn) In fact (let ((x1 expr1) ⋮ (xn exprn)) body) is essentially equivalent to: ((lambda (x1 … xn) body) expr1 … exprn)

• This calls a function that's the same as my-helper-function but does not give the function a name.

Page 57: LET and LET*

57

Evaluation of (let ((x1 expr1) ⋮ (xn exprn)) body) is roughly equivalent to making a definition (defun my-helper-function (x1 … xn) body) and then calling the function as follows: (my-helper-function expr1 … exprn) In fact (let ((x1 expr1) ⋮ (xn exprn)) body) is essentially equivalent to: ((lambda (x1 … xn) body) expr1 … exprn)

• The latter expression calls a function that's the same as my-helper-function but has not been given a name.

Page 58: LET and LET*

58

LET*

LET* forms are equivalent to nested LET forms:

(let* ((x1 expr1) (let ((x1 expr1)) (x2 expr2) = (let ((x2 expr2)) ⋮ ⋱ (xn exprn)) (let ((xn exprn)) body) body) … ))

Page 59: LET and LET*

59

LET*

LET* forms are equivalent to nested LET forms:

(let* ((x1 expr1) (let ((x1 expr1)) (x2 expr2) = (let ((x2 expr2)) ⋮ ⋱ (xn exprn)) (let ((xn exprn)) body) body) … ))

• \f

Page 60: LET and LET*

60

LET*

LET* forms are equivalent to nested LET forms:

(let* ((x1 expr1) (let ((x1 expr1)) (x2 expr2) = (let ((x2 expr2)) ⋮ ⋱ (xn exprn)) (let ((xn exprn)) body) body) … ))

• Thus for 2 ≤ k ≤ n each expression exprk can use the previous local variables x1, … , xk–1 (which would not be the case if we replaced LET* with LET).

Page 61: LET and LET*

61

LET*

LET* forms are equivalent to nested LET forms:

(let* ((x1 expr1) (let ((x1 expr1)) (x2 expr2) = (let ((x2 expr2)) ⋮ ⋱ (xn exprn)) (let ((xn exprn)) body) body) … ))

• Thus for 2 ≤ k ≤ n each expression exprk can use the previous local variables x1, … , xk–1 (which would not be the case if we replaced LET* with LET).

On p. 144 of Touretzky, the difference between LET* and LET is described as follows:

Page 62: LET and LET*

62

From p. 144 of Touretzky:

Page 63: LET and LET*

63

From p. 144 of Touretzky:

Page 64: LET and LET*

64

From p. 144 of Touretzky:

Page 65: LET and LET*

65

From p. 144 of Touretzky:

Page 66: LET and LET*

66

From p. 144 of Touretzky:

Page 67: LET and LET*

67

From p. 144 of Touretzky:

Page 68: LET and LET*

68

From p. 144 of Touretzky:

Page 69: LET and LET*

69

From p. 145 of Touretzky:

Page 70: LET and LET*

70

From p. 145 of Touretzky:

Page 71: LET and LET*

71

From p. 145 of Touretzky:

Page 72: LET and LET*

72

The following explanation of the difference between LET and LET* appears on p. 391 of Sethi (p. 7 of the course reader):

Page 73: LET and LET*

73

The following explanation of the difference between LET and LET* appears on p. 391 of Sethi (p. 7 of the course reader):

Use (setf x 0) here in Common Lisp.

Page 74: LET and LET*

74

The following explanation of the difference between LET and LET* appears on p. 391 of Sethi (p. 7 of the course reader):

Use (setf x 0) here in Common Lisp.

Page 75: LET and LET*

75

The following explanation of the difference between LET and LET* appears on p. 391 of Sethi (p. 7 of the course reader):

Use (setf x 0) here in Common Lisp.

Page 76: LET and LET*

76

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11

Page 77: LET and LET*

77

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11 Replacing let with let*, we get: Evaluation of (h* 3 4 7):

(defun h* (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let* ((x (sqrt x)) local x ⇒ 2 (y (* x 2)) local y ⇒ 4 (z (+ x y))) local z ⇒ 6 (/ (+ x y z) w)) LET* ⇒ (2+4+6)/3 = 4 x)) x ⇒ 4

(h* 3 4 7) ⇒ 4+4 = 8

Page 78: LET and LET*

78

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11 Replacing let with let*, we get: Evaluation of (h* 3 4 7):

(defun h* (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let* ((x (sqrt x)) local x ⇒ 2 (y (* x 2)) local y ⇒ 4 (z (+ x y))) local z ⇒ 6 (/ (+ x y z) w)) LET* ⇒ (2+4+6)/3 = 4 x)) x

(h* 3 4 7) ⇒ 4+4 = 8

Page 79: LET and LET*

79

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11 Replacing let with let*, we get: Evaluation of (h* 3 4 7):

(defun h* (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let* ((x (sqrt x)) the LET*'s local x ⇒ 2 (y (* x 2)) the LET*'s local y ⇒ 4 (z (+ x y))) the LET*'s local z ⇒ 6 (/ (+ x y z) w)) LET* ⇒ (2+4+6)/3 = 4 x)) x ⇒ 4

(h* 3 4 7) ⇒ 4+4 = 8

Page 80: LET and LET*

80

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11 Replacing let with let*, we get: Evaluation of (h* 3 4 7):

(defun h* (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let* ((x (sqrt x)) the LET*'s local x ⇒ 2 (y (* x 2)) the LET*'s local y ⇒ 4 (z (+ x y))) the LET*'s local z ⇒ 6 (/ (+ x y z) w)) LET* ⇒ (2+4+6)/3 = 4 x)) x ⇒ 4

(h* 3 4 7) ⇒ 4+4 = 8

Page 81: LET and LET*

81

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11 Replacing let with let*, we get: Evaluation of (h* 3 4 7):

(defun h* (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let* ((x (sqrt x)) the LET*'s local x ⇒ 2 (y (* x 2)) the LET*'s local y ⇒ 4 (z (+ x y))) the LET*'s local z ⇒ 6 (/ (+ x y z) w)) LET* ⇒ (2+4+6)/3 = 4 x)) x ⇒ 4

(h* 3 4 7) ⇒ 4+4 = 8

Page 82: LET and LET*

82

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11 Replacing let with let*, we get: Evaluation of (h* 3 4 7):

(defun h* (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let* ((x (sqrt x)) the LET*'s local x ⇒ 2 (y (* x 2)) the LET*'s local y ⇒ 4 (z (+ x y))) the LET*'s local z ⇒ 6 (/ (+ x y z) w)) LET* ⇒ (2+4+6)/3 = 4 x)) x ⇒ 4

(h* 3 4 7) ⇒ 4+4 = 8

Page 83: LET and LET*

83

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11 Replacing let with let*, we get: Evaluation of (h* 3 4 7):

(defun h* (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let* ((x (sqrt x)) the LET*'s local x ⇒ 2 (y (* x 2)) the LET*'s local y ⇒ 4 (z (+ x y))) the LET*'s local z ⇒ 6 (/ (+ x y z) w)) LET* ⇒ (2+4+6)/3 = 4 x)) x ⇒ 4

(h* 3 4 7) ⇒ 4+4 = 8

Page 84: LET and LET*

84

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11 Replacing let with let*, we get: Evaluation of (h* 3 4 7):

(defun h* (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let* ((x (sqrt x)) the LET*'s local x ⇒ 2 (y (* x 2)) the LET*'s local y ⇒ 4 (z (+ x y))) the LET*'s local z ⇒ 6 (/ (+ x y z) w)) LET* ⇒ (2+4+6)/3 = 4 x)) x ⇒ 4

(h* 3 4 7) ⇒ 4+4 = 8

Page 85: LET and LET*

85

Recall: A related example: Evaluation of (h 3 4 7):

(defun h (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let ((x (sqrt x)) the LET's local x ⇒ 2 (y (* x 2)) the LET's local y ⇒ 8 (z (+ x y))) the LET's local z ⇒ 11 (/ (+ x y z) w)) LET ⇒ (2+8+11)/3 = 7 x)) x ⇒ 4

(h 3 4 7) ⇒ 7+4 = 11 Replacing let with let*, we get: Evaluation of (h* 3 4 7):

(defun h* (w x y) w ⇒ 3 x ⇒ 4 y ⇒ 7 (+ (let* ((x (sqrt x)) the LET*'s local x ⇒ 2 (y (* x 2)) the LET*'s local y ⇒ 4 (z (+ x y))) the LET*'s local z ⇒ 6 (/ (+ x y z) w)) LET* ⇒ (2+4+6)/3 = 4 x)) x ⇒ 4

(h* 3 4 7) ⇒ 4+4 = 8

Page 86: LET and LET*

86

Recursive Functions

Page 87: LET and LET*

87

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, it's good to first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f, but when our version is called with an argument value x it is only allowed to call the supposedly already written f with an argument value that is smaller in size than x.

• In more sophisticated recursion we may occasionally relax the "smaller in size than x" condition, but then we have to carefully check that our function terminates.

Example

Page 88: LET and LET*

88

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f, but when our version is called with an argument value x it is only allowed to call the supposedly already written f with an argument value that is smaller in size than x.

• In more sophisticated recursion we may occasionally relax the "smaller in size than x" condition, but then we have to carefully check that our function terminates.

Example

Page 89: LET and LET*

89

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f; but when our version is called with an argument value x, it is only allowed to call the supposedly already written f with an argument value that is valid for f and smaller in size than x.

• In more sophisticated recursion we may occasionally relax the "smaller in size than x" condition, but then we have to carefully check that our function terminates.

Example

Page 90: LET and LET*

90

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f; but when our version is called with an argument value x, it is only allowed to call the supposedly already written f with an argument value that is valid for f and smaller in size than x.

• In more sophisticated recursion we may occasionally relax this "smaller in size than x" condition, but then we have to carefully check that our function terminates!

Example

Page 91: LET and LET*

91

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f; but when our version is called with an argument value x, it is only allowed to call the supposedly already written f with an argument value that is valid for f and smaller in size than x.

• In more sophisticated recursion we may occasionally relax this "smaller in size than x" condition, but then we have to carefully check that our function terminates!

Example Write a function length-of such that:

If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Page 92: LET and LET*

92

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f; but when our version is called with an argument value x, it is only allowed to call the supposedly already written f with an argument value that is valid for f and smaller in size than x.

• In more sophisticated recursion we may occasionally relax the "smaller in size than x" condition, but then we have to carefully check that our function terminates.

Example Write a function length-of such that:

If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Page 93: LET and LET*

93

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f; but when our version is called with an argument value x, it is only allowed to call the supposedly already written f with an argument value that is valid for f and smaller in size than x.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Page 94: LET and LET*

94

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f; but when our version is called with an argument value x, it is only allowed to call the supposedly already written f with an argument value that is valid for f and smaller in size than x.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works provided L ⇒ a nonempty list:

Page 95: LET and LET*

95

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f; but when our version is called with an argument value x, it is only allowed to call the supposedly already written f with an argument value that is valid for f and smaller in size than x.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works provided L ⇒ a nonempty list:

(defun my-length-of (L) (let ((X (length-of (cdr L)))) (+ X 1)))

Page 96: LET and LET*

96

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f; but when our version is called with an argument value x, it is only allowed to call the supposedly already written f with an argument value that is valid for f and smaller in size than x.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works provided L ⇒ a nonempty list:

(defun my-length-of (L) (let ((X (length-of (cdr L)))) (+ X 1)))

• If L ⇒ NIL, this violates the "call the supposedly already written f with an argument value that is smaller" condition.

Page 97: LET and LET*

97

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f; but when our version is called with an argument value x, it is only allowed to call the supposedly already written f with an argument value that is valid for f and smaller in size than x.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works provided L ⇒ a nonempty list:

(defun my-length-of (L) (let ((X (length-of (cdr L)))) (+ X 1)))

• If L ⇒ NIL, this violates the "call the supposedly already written f with an argument value that is … smaller" condition.

Page 98: LET and LET*

98

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

• Our own version of f can call the supposedly already written f, but when our version is called with an argument value x it is only allowed to call the supposedly already written f with an argument value that is smaller in size than x.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works provided L ⇒ a nonempty list:

(defun my-length-of (L) (let ((X (length-of (cdr L)))) (+ X 1)))

Page 99: LET and LET*

99

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works provided L ⇒ a nonempty list:

(defun my-length-of (L) (let ((X (length-of (cdr L)))) (+ X 1)))

Page 100: LET and LET*

100

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works provided L ⇒ a nonempty list:

(defun my-length-of (L) (let ((X (length-of (cdr L)))) (+ X 1)))

To make our function good even when L ⇒ NIL, we add a case:

Page 101: LET and LET*

101

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works provided L ⇒ a nonempty list:

(defun my-length-of (L) (let ((X (length-of (cdr L)))) (+ X 1)))

To make our function good even when L ⇒ NIL, we add a case:

(defun better-my-length-of (L) (if (null L) 0 (let ((X (length-of (cdr L)))) (+ X 1))))

Page 102: LET and LET*

102

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works: provided L ⇒ a nonempty list:

(defun my-length-of (L) (let ((X (length-of (cdr L)))) (+ X 1)))

To make our function good even when L ⇒ NIL, we add a case:

(defun better-my-length-of (L) (if (null L) 0 (let ((X (length-of (cdr L)))) (+ X 1))))

Page 103: LET and LET*

103

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works: provided L ⇒ a nonempty list:

(defun better-my-length-of (L) (if (null L) 0 (let ((X (length-of (cdr L)))) (+ X 1))))

Page 104: LET and LET*

104

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works: provided L ⇒ a nonempty list:

(defun better-my-length-of (L) (if (null L) 0 (let ((X (length-of (cdr L)))) (+ X 1))))

But this still assumes length-of has already been written.

Q. How can we write length-of? A.

Page 105: LET and LET*

105

Writing Recursive Functions That Take 1 Argument, Which is a Proper List or a Nonnegative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

Assuming length-of has already been written, here is a function that works: provided L ⇒ a nonempty list:

(defun better-my-length-of (L) (if (null L) 0 (let ((X (length-of (cdr L)))) (+ X 1))))

But this still assumes length-of has already been written.

Q. How can we write length-of? A. We simply rename better-my-length-of to length-of!

Page 106: LET and LET*

106

Writing Recursive Functions That Take 1 Argument, Which is a List or a Non-Negative Integer

• When writing a recursive function f, we can first suppose a function f that correctly solves the same problem has already been written.

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) 0 (let ((X (length-of (cdr L)))) (+ X 1))))

But this still assumes length-of has already been written.

Q. How can we write length-of? A. We simply rename better-my-length-of to length-of!

≡≡≡≡≡≡≡

Page 107: LET and LET*

107

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) 0 (let ((X (length-of (cdr L)))) (+ X 1))))

Q. How can we write length-of? A. We simply rename better-my-length-of to length-of!

≡≡≡≡≡≡≡

Page 108: LET and LET*

108

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

Q. How can we write length-of? A. We simply rename better-my-length-of to length-of!

• This definition of length-of is not circular, because when length-of calls itself it always passes an argument value that is smaller than the argument value it received.

≡≡≡≡≡≡≡

Page 109: LET and LET*

109

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

Q. How can we write length-of? A. We simply rename better-my-length-of to length-of!

• This definition of length-of is not circular, because when length-of calls itself it always passes an argument value that is smaller than the argument value it received.

≡≡≡≡≡≡≡

Page 110: LET and LET*

110

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• This definition of length-of is not circular, because when length-of calls itself it always passes an argument value that is smaller than the argument value it received.

• A call (length-of L) returns the right result if its recursive call (length-of (cdr L)) returns the right result.

• So, for all n > 0, if (length-of l) returns the right result whenever l ⇒ a list of length < n, then (length-of l) also returns the right result whenever l ⇒ a list of length n.

• Example: If (length-of l) returns the right result whenever l ⇒ a list of length 0, 1, 2, 3, or 4, then (length-of l) also returns the right result whenever l ⇒ a list of length 5.

≡≡≡≡≡≡≡

Page 111: LET and LET*

111

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• This definition of length-of is not circular, because when length-of calls itself it always passes an argument value that is smaller than the argument value it received.

• If a recursive call (length-of (cdr L)) returns the right result, then the call (length-of L) returns the right result.

• So, for all n > 0, if (length-of l) returns the right result whenever l ⇒ a list of length < n, then (length-of l) also returns the right result whenever l ⇒ a list of length n.

• Example: If (length-of l) returns the right result whenever l ⇒ a list of length 0, 1, 2, 3, or 4, then (length-of l) also returns the right result whenever l ⇒ a list of length 5.

≡≡≡≡≡≡≡

Page 112: LET and LET*

112

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• This definition of length-of is not circular, because when length-of calls itself it always passes an argument value that is smaller than the argument value it received.

• If a recursive call (length-of (cdr L)) returns the right result, then the call (length-of L) returns the right result.

• So, for all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• Example: If (length-of l) returns the right result whenever l ⇒ a list of length 0, 1, 2, 3, or 4, then (length-of l) also returns the right result whenever l ⇒ a list of length 5.

≡≡≡≡≡≡≡

Page 113: LET and LET*

113

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• This definition of length-of is not circular, because when length-of calls itself it always passes an argument value that is smaller than the argument value it received.

• If a recursive call (length-of (cdr L)) returns the right result, then the call (length-of L) returns the right result.

• So, for all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• Example: If (length-of l) returns the right result when l ⇒ a proper list of length 0, 1, 2, or 3, then (length-of l) returns the right result when l ⇒ a proper list of length 4.

≡≡≡≡≡≡≡

Page 114: LET and LET*

114

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• This definition of length-of is not circular, because when length-of calls itself it always passes an argument value that is smaller than the argument value it received.

• If a recursive call (length-of (cdr L)) returns the right result, then the call (length-of L) returns the right result.

• So, For all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• Example: If (length-of l) returns the right result when l ⇒ a proper list of length 0, 1, 2, or 3, then (length-of l) returns the right result when l ⇒ a proper list of length 4.

≡≡≡≡≡≡≡

Page 115: LET and LET*

115

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• For all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• Example: If (length-of l) returns the right result when l ⇒ a proper list of length 0, 1, 2, or 3, then (length-of l) returns the right result when l ⇒ a proper list of length 4.

≡≡≡≡≡≡≡

Page 116: LET and LET*

116

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• For all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• Example: If (length-of l) returns the right result when l ⇒ a proper list of length 0, 1, 2, or 3, then (length-of l) returns the right result when l ⇒ a proper list of length 4.

• (length-of l) returns the right result (i.e., 0) when l ⇒ a list of length 0.

≡≡≡≡≡≡≡

Page 117: LET and LET*

117

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• For all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• Example: If (length-of l) returns the right result when l ⇒ a proper list of length 0, 1, 2, or 3, then (length-of l) returns the right result when l ⇒ a proper list of length 4.

• (length-of l) returns the right result (i.e., 0) when l ⇒ a list of length 0.

∴ If l ⇒ a proper list of any length, then (length-of l) ⇒ the right result (i.e., l's length).

≡≡≡≡≡≡≡

Page 118: LET and LET*

118

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• For all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• Example: If (length-of l) returns the right result when l ⇒ a proper list of length 0, 1, 2, or 3, then (length-of l) returns the right result when l ⇒ a proper list of length 4.

• (length-of l) returns the right result (i.e., 0) when l ⇒ a list of length 0.

∴ If l ⇒ a proper list of any length, then (length-of l) ⇒ the right result (i.e., l's length).

≡≡≡≡≡≡≡

Page 119: LET and LET*

119

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• For all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• (length-of l) returns the right result (i.e., 0) when l ⇒ a list of length 0.

∴ If l ⇒ a proper list of any length, then (length-of l) ⇒ the right result (i.e., l's length).

≡≡≡≡≡≡≡

Page 120: LET and LET*

120

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• For all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• (length-of l) returns the right result (i.e., 0) when l ⇒ a list of length 0.

∴ If l ⇒ a proper list of any length, then (length-of l) ⇒ the right result (i.e., l's length).

• Although this function is correct as written, we can improve / simplify the definition by eliminating the LET, because its local variable X is never used more than once.

We then replace the X in (+ X 1) with (length-of (cdr L)):

≡≡≡≡≡≡≡

Page 121: LET and LET*

121

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1))))

• For all n > 0, if (length-of l) returns the right result when l ⇒ a proper list of length < n, then (length-of l) returns the right result when l ⇒ a proper list of length n.

• (length-of l) returns the right result (i.e., 0) when l ⇒ a list of length 0.

∴ If l ⇒ a proper list of any length, then (length-of l) ⇒ the right result (i.e., l's length).

• Although this function is correct as written, we can improve / simplify the definition by eliminating the LET, because its local variable X is never used more than once.

We then replace the X in (+ X 1) with (length-of (cdr L)):

≡≡≡≡≡≡≡

Page 122: LET and LET*

122

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1)))) • Although this function is correct as written, we can improve / simplify the definition by eliminating the LET, because its local variable X is never used more than once. We then replace the X in (+ X 1) with (length-of (cdr L)):

≡≡≡≡≡≡≡

Page 123: LET and LET*

123

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1)))) • Although this function is correct as written, we can improve / simplify the definition by eliminating the LET, because its local variable X is never used more than once. We then replace the X in (+ X 1) with (length-of (cdr L)):

(defun length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X (length-of (cdr L)) 1) ) ))

≡≡≡≡≡≡≡

≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡

Page 124: LET and LET*

124

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1)))) • Although this function is correct as written, we can improve / simplify the definition by eliminating the LET, because its local variable X is never used more than once. We then replace the X in (+ X 1) with (length-of (cdr L)):

(defun length-of (L) (if (null L) ; base case, where there's no recursive call 0 (+ (length-of (cdr L)) 1)))

≡≡≡≡≡≡≡

Page 125: LET and LET*

125

Example Write a function length-of such that: If l ⇒ a proper list, then (length-of l) ⇒ the length of l.

(defun better-my-length-of (L) (if (null L) ; base case, where there's no recursive call 0 (let ((X (length-of (cdr L)))) (+ X 1)))) • Although this function is correct as written, we can improve / simplify the definition by eliminating the LET, because its local variable X is never used more than once. We then replace the X in (+ X 1) with (length-of (cdr L)):

(defun length-of (L) (if (null L) ; base case, where there's no recursive call 0 (+ (length-of (cdr L)) 1)))

• We've given a written explanation of a possible thought process that leads to this definition, but an experienced Lisp programmer would likely code simple definitions like this one without giving any explanation!

≡≡≡≡≡≡≡