Lecture 5 Slides - Lecture Slides

1 of 63

Lecture 5

Lambda Abstraction

2 of 63

Rules of computation in ISL+

  • If it’s a constant (a number or string)
    • It’s its own value
    • Return it

​

  • If it’s a variable name (e.g. a word, hyphenated-phrase, or symbol like +)
    • Look up its value in the dictionary
    • Return (output) it

​

  • If it has parens (i.e.(a b c …))
    • Check if it’s a special case
      • (define name value)�Update dictionary to list value as definition of name.
      • (λ (input-names …) output-exp)�Makes a new function, whose inputs are called input-names and whose output is computed by output-exp.
    • Otherwise, find the values of a, b, c, etc. using these same rules
      • The value of a had better be a function
      • Call it with the values of b, c, etc. as inputs
      • Return its output

3 of 63

the substitution model

4 of 63

The substitution model

  • The SICP book teaches a model of how function calls operate called the substitution model
  • Based on algebraic simplification
    • Calls to primitive functions work by replacing the call with the value of its output
    • Calls to compound functions are computed by
      • Replacing the call with the body of the function
      • Replace the argument names with their values
      • So ((λ (n) (+ n 1)) 5)
        • (+ n 1), remembering n is 5
        • (+ 5 1)

5 of 63

What is the value of this expression?

> ((λ (n) (+ n 1))

3)

​

  • Find the values of the subexpressions
    • λ expression is a function
    • 3 is the number 3
  • Call the function with 3 as its argument
    • Substitute 3 for n in (+ n 1) to get (+ 3 1)
    • Execute (+ 3 1)
    • Output of λ expression is 4
  • Value of the overall expression is 4

6 of 63

What is the value of this expression?

> ((λ (n) (+ n 1)) 3)

> 4

  • The rules are very simple
  • But interact in subtle ways

7 of 63

Making a�color gradient

8 of 63

Drawing a line

  • How do we make a 100 pixel vertical line?

9 of 63

Drawing a line

  • How do we make a 100 pixel vertical line?

​

(rectangle 1 100 "solid" "blue")

​

10 of 63

Drawing a line

  • How do we make it two pixels wide?

​

(rectangle 1 100 "solid" "blue")

​

11 of 63

Drawing a line

  • How do we make it two pixels wide?

​

(rectangle 2 100 "solid" "blue")

​

12 of 63

Drawing a line

  • How do we make it three pixels wide?

​

(rectangle 2 100 "solid" "blue")

​

13 of 63

Drawing a line

  • How do we make it three pixels wide?

​

(rectangle 3 100 "solid" "blue")

​

14 of 63

Drawing a line

  • How do we make a function that creates lines of specified widths?

​

(rectangle 3 100 "solid" "blue")

​

15 of 63

Drawing lines "à la mode"

  • How do we make a function that creates lines of specified widths?

​

(λ (width)

(rectangle width 100 "solid" "blue"))

​

16 of 63

Even more customization

  • How can we modify the function to change the color based on the width?

​

(λ (width)

(rectangle width 100 "solid" "blue"))

​

17 of 63

Even more customization

  • How can we modify the function to change the color based on the width?

​

(λ (width)

(rectangle width

100

"solid"

(color 0

0

(- 255

(* width 10)))))

18 of 63

MORE LINES

  • How do we make a series of lines?

​

(λ (width)

(rectangle width

100

"solid"

(color 0

0

(- 255

(* width 10)))))

19 of 63

MORE LINES

  • How do we make a series of lines?

​

(iterated-beside (λ (width)

(rectangle width

100

"solid"

(color 0

0

(- 255

(* width 10)))))

10)

20 of 63

Reading the Code

​

​

(iterated-beside (λ (width)

(rectangle width

100

"solid"

(color 0

0

(- 255

(* width 10)))))

10)

calls the line generator

repeatedly and collects the results

generates a single line

number of lines to make

21 of 63

Stretching

  • How do we make the lines wider?

​

​

​

​

​

(iterated-beside (λ (width)

(rectangle width

100

“solid”

(color 0

0

(- 255

(* width 10)))))

10)

22 of 63

Stretching

  • How do we make the lines wider?

​

​

​

​

​

(iterated-beside (λ (width)

(rectangle (* 10 width)

100

“solid”

(color 0

0

(- 255

(* width 10)))))

10)

23 of 63

Changing the Palette

  • How do we make them shift from blue to green?

​

​

​

(iterated-beside (λ (width)

(rectangle (* 10 width)

100

“solid”

(color 0

0

(- 255

(* width 10)))))

10)

24 of 63

Changing the Palette

  • How do we make them shift from blue to green?

​

​

​

(iterated-beside (λ (width)

(rectangle (* 10 width)

100

“solid”

(color 0

(* width 25)

(- 255

(* width 25)))))

10)

25 of 63

Lambda abstraction

26 of 63

Functional abstraction

“Variablizing” expressions to generalize them

  • The expression (rectangle width 100 "solid" "blue") doesn’t express any particular line
    • It expresses vertical 100 pixel high blue lines
    • Without specifying which vertical 100 pixel blue line we mean
      • (i.e. which width we mean)

27 of 63

Abstracting expressions

  • A good method for writing simple functions:
    1. Think of what its output should be in some specific test case
    2. Write an expression for it
    3. Change the part(s) you want to vary to a variable
    4. Wrap it with (λ (variable) … )
  • This is called abstracting the expression
    • Or, if you want to be fancy, you can call it λ-abstraction

(rectangle 1 100

"solid" "blue")

​

(rectangle width 100

"solid" "blue")

​

(λ (width)

(rectangle width

100

"solid"

"blue"))

​

28 of 63

Abstracting expressions

Alas, it’s often not that simple

  • You may need to modify the input before it’s really in the form you want
  • Or experiment with it a bit to make it work the way you really want

(rectangle 1 100

"solid" "blue")

​

(rectangle width 100

"solid" "blue")

​

(λ (width)

(rectangle width 100

"solid" "blue"))

​

(λ (width)

(rectangle (* 10 width)

100

"solid"

"blue"))

​

29 of 63

Making a rotary pattern

How do we make a pattern of rectangles rotating around a central point?

30 of 63

Start simple

How do we make one rectangle?

31 of 63

Start simple

How do we make one rectangle?

​

(rectangle 50 200

"solid" "red")

32 of 63

Get slightly closer

How do we rotate one rectangle?

​

(rectangle 50 200

"solid" "red")

33 of 63

Get slightly closer

How do we rotate one rectangle?

​

(rotate 30

(rectangle 50 200

"solid" "red"))

34 of 63

Get slightly closer

How do we rotate one rectangle by an arbitrary angle?

​

(rotate 30

(rectangle 50 200

"solid" "red"))

35 of 63

Get slightly closer

How do we rotate one rectangle by an arbitrary angle?

​

(rotate degrees

(rectangle 50 200

"solid" "red"))

36 of 63

Make a function to do it!

How do we make a function to create arbitrary rotated rectangles?

​

(rotate degrees

(rectangle 50 200

"solid" "red"))

37 of 63

Make a function to do it!

How do we make a function to create arbitrary rotated rectangles?

​

(λ (degrees)

(rotate degrees

(rectangle 50 200

"solid" "red")))

38 of 63

Use the function you made

How do we make many rotated rectangles?

​

(λ (degrees)

(rotate degrees

(rectangle 50 200

"solid" "red")))

39 of 63

Use the function you made

How do we make many rotated rectangles?

​

(iterated-overlay (λ (degrees)

(rotate degrees

(rectangle 50 200

"solid" "red")))

50)

​

40 of 63

Use the function you made

How do we separate them more?

​

(iterated-overlay (λ (degrees)

(rotate degrees

(rectangle 50 200

"solid" "red")))

50)

​

41 of 63

Use the function you made

How do we separate them more?

​

(iterated-overlay (λ (degrees)

(rotate (* 36 degrees)

(rectangle 50 200

"solid" "red")))

5)

​

42 of 63

Further Parameterize

How do we separate them more?

​

(iterated-overlay (λ (current-count)

(rotate (* 36 current-count)

(rectangle 50 200

"solid" "red")))

5)

​

43 of 63

Further Parameterize

How do we vary the color?

​

(iterated-overlay (λ (current-count)

(rotate (* 36 current-count)

(rectangle 50 200

"solid" "red")))

5)

​

44 of 63

Further Parameterize

How do we vary the color?

​

(iterated-overlay (λ (current-count)

(rotate (* 36 current-count)

(rectangle 50 200

"solid"

(color (- 200 (* current-count 50))

(* current-count 50)

0))))

5)

​

​

45 of 63

Interpolating colors

(interpolate-colors color-1 color-2 frac)

Allows you to create colors between to colors specified by some frac.

  • A frac of 0 means the color will just be color-1
  • A frac of 1 means the color will just be color-2
  • A frac of 0.5 means the color will be halfway between color-1 and color-2

46 of 63

Further Parameterize

How do we vary the color?

​

(iterated-overlay (λ (current-count)

(rotate (* 36 current-count)

(rectangle 50 200

"solid"

(interpolate-colors (color 255 0 0)

(color 0 255 0))

(/ current-count 4)))

5)

​

​

47 of 63

Further Parameterize

How do we vary the color?

​

(iterated-overlay (λ (current-count)

(rotate (* 36 current-count)

(rectangle 50 200

"solid"

(interpolate-colors (color 255 0 0)

(color 0 255 0))

(/ current-count 4)))

5)

​

​

48 of 63

Further Parameterize

How do we turn it into a function with any number of spokes?

​

(iterated-overlay (λ (current-count)

(rotate (* 36 current-count)

(rectangle 50 200

"solid"

(interpolate-colors (color 255 0 0)

(color 0 255 0))

(/ current-count 4)))

5)

​

​

49 of 63

Grids revisited

50 of 63

How do we make a row of items?

​

​

​

​

​

​

​

  • How do we write a function that makes rows of items?

51 of 63

Making a row

;; row: image number -> image

;; Makes an row of copies of item

(define row (λ (item count)

(iterated-beside ;; number -> image

;; Just returns item

(λ (ignore) item)

count)))

52 of 63

Wait…can you do that?

;; row: image number -> image

;; Makes an row of copies of item

(define row (λ (item count)

(iterated-beside ;; number -> image

;; Just returns item

(λ (ignore) item)

count)))

​

  • The inner function doesn’t use its argument
  • It ignores it and always returns the same output
  • That’s fine; it’s a common thing to do

53 of 63

But then why bother with a function (aka procedure)?

;; row: image number -> image

;; Makes an row of copies of item

(define row (λ (item count)

(iterated-beside item

count)))

​

  • Couldn't we just do this?

​

54 of 63

That won’t work

​

​

​

​

  • We'd be passing the square image itself to iterated-beside
    • It needs its input to be a function
    • But we’re passing it an image
    • So it throws an argument type exception

55 of 63

How do we make a column?

56 of 63

Making a column

;; column: image number -> image

;; Makes an stack of copies of item

(define column (λ (item count)

(iterated-above (λ (ignore) item)

count))

57 of 63

How do we make a grid?

58 of 63

Making a grid

;; grid: image number number -> image

;; Makes an grid of copies of item

(define grid

(λ (item columns rows)

(column (row item columns)

rows)))

​

59 of 63

Take the item

;; grid: image number number -> image

;; Makes an grid of copies of item

(define grid

(λ (item columns rows)

(column (row item columns)

rows)))

​

60 of 63

Make a row of them

;; grid: image number number -> image

;; Makes an grid of copies of item

(define grid

(λ (item columns rows)

(column (row item columns)

rows)))

​

61 of 63

Make a stack of them

;; grid: image number number -> image

;; Makes an grid of copies of item

(define grid

(λ (item columns rows)

(column (row item columns)

rows)))

​

62 of 63

Make a function that does that

;; grid: image number number -> image

;; Makes an grid of copies of item

(define grid

(λ (item columns rows)

(column (row item columns)

rows)))

​

63 of 63

Name it grid

;; grid: image number number -> image

;; Makes an grid of copies of item

(define grid

(λ (item columns rows)

(column (row item columns)

rows)))

​