Lecture 6 Slides - Lambda Abstraction

1 of 68

Lecture 6 (Pre-Recorded)

Lambda Abstraction

2 of 68

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 68

the substitution model

4 of 68

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 68

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 68

What is the value of this expression?

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

> 4

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

7 of 68

Making a�color gradient

8 of 68

Drawing a line

  • How do we make a 100 pixel vertical line?

9 of 68

Drawing a line

  • How do we make a 100 pixel vertical line?

(rectangle 1 100 "solid" "blue")

10 of 68

Drawing a line

  • How do we make it two pixels wide?

(rectangle 1 100 "solid" "blue")

11 of 68

Drawing a line

  • How do we make it two pixels wide?

(rectangle 2 100 "solid" "blue")

12 of 68

Drawing a line

  • How do we make it three pixels wide?

(rectangle 2 100 "solid" "blue")

13 of 68

Drawing a line

  • How do we make it three pixels wide?

(rectangle 3 100 "solid" "blue")

14 of 68

Drawing a line

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

(rectangle 3 100 "solid" "blue")

15 of 68

Drawing lines "à la mode"

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

(λ (width)

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

16 of 68

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 68

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 68

MORE LINES

  • How do we make a series of lines?

(λ (width)

(rectangle width

100

"solid"

(color 0

0

(- 255

(* width 10)))))

19 of 68

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 68

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 68

Stretching

  • How do we make the lines wider?

(iterated-beside (λ (width)

(rectangle width

100

“solid”

(color 0

0

(- 255

(* width 10)))))

10)

22 of 68

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 68

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 68

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 68

Lambda abstraction

26 of 68

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 blue lines
    • Without specifying which vertical 100 pixel blue line we mean
      • (i.e. which width we mean)

27 of 68

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 68

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 68

Making a rotary pattern

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

30 of 68

Start simple

How do we make one rectangle?

31 of 68

Start simple

How do we make one rectangle?

(rectangle 50 200

"solid" "red")

32 of 68

Get slightly closer

How do we rotate one rectangle?

(rectangle 50 200

"solid" "red")

33 of 68

Get slightly closer

How do we rotate one rectangle?

(rotate 30

(rectangle 50 200

"solid" "red"))

34 of 68

Get slightly closer

How do we rotate one rectangle by an arbitrary angle?

(rotate 30

(rectangle 50 200

"solid" "red"))

35 of 68

Get slightly closer

How do we rotate one rectangle by an arbitrary angle?

(rotate degrees

(rectangle 50 200

"solid" "red"))

36 of 68

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 68

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 68

Use the function you made

How do we make many rotated rectangles?

(λ (degrees)

(rotate degrees

(rectangle 50 200

"solid" "red")))

39 of 68

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 68

Use the function you made

How do we separate them more?

(iterated-overlay (λ (degrees)

(rotate degrees

(rectangle 50 200

"solid" "red")))

50)

41 of 68

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 68

Further Parameterize

How do we separate them more?

(iterated-overlay (λ (picture-num)

(rotate (* 36 picture-num)

(rectangle 50 200

"solid" "red")))

5)

43 of 68

Further Parameterize

How do we vary the color?

(iterated-overlay (λ (picture-num)

(rotate (* 36 picture-num)

(rectangle 50 200

"solid" "red")))

5)

44 of 68

Further Parameterize

How do we vary the color?

(iterated-overlay (λ (picture-num)

(rotate (* 36 picture-num)

(rectangle 50 200

"solid"

(color (- 200 (* picture-num 50))

(* picture-num 50)

0))))

5)

45 of 68

Make it into a Function

How do we functionalize it?

(iterated-overlay (λ (picture-num)

(rotate (* 36 picture-num)

(rectangle 50 200

"solid"

(color (- 200 (* picture-num 50))

(* picture-num 50)

0))))

5)

46 of 68

Make it into a function

How do we functionalize it?

(define rotary (λ (num-spokes)

(iterated-overlay

(λ (picture-num)

(rotate (* (quotient 360 (* 2 num-spokes)) picture-num)

(rectangle 50 200

"solid"

(color (- 255 (* picture-num (quotient 255 num-spokes)))

(* picture-num (quotient 255 num-spokes))

0))))

num-spokes)))

47 of 68

Local variables

Another abstraction tool

48 of 68

We keep dividing the same thing…

;; rotary: number -> image

;; creates a rotary image with rectangles that change color

(define rotary (λ (num-spokes)

(iterated-overlay

(λ (picture-num)

(rotate (* (quotient 360 (* 2 num-spokes)) picture-num)

(rectangle 50 200

"solid"

(color (- 255

(* picture-num

(quotient 255

num-spokes)))

(* picture-num

(quotient 255

num-spokes))

0))))

num-spokes)))

49 of 68

Local names in Racket

(local [(define name1 value1)

(define name2 value2)

(define namen valuen)]�output-expression)

  • Local names (also known as local variables or temporary variables) are names that are only in effect for a single expression
  • Sort of like pronouns in English

50 of 68

Local names in Racket

(local [(define name1 value1)

(define name2 value2)

(define namen valuen)]�output-expression)

  • Computes all the values
  • Substitutes them for their respective names in output-expression
  • Runs output-expression and returns its value

51 of 68

Saving some redundant work

;; rotary: number -> image

;; creates a rotary image with rectangles that change color

(define rotary-2 (λ (num-spokes)

(iterated-overlay

(λ (picture-num)

(local [(define q (quotient 250 num-spokes))]

(rotate (* (quotient 360 (* 2 num-spokes)) picture-num)

(rectangle 50 200

"solid"

(color (- 255

(* picture-num

q))

(* picture-num

q)

0)))))

num-spokes)))

52 of 68

Rules of computation in ISL+

Look at the expression

  • If it’s a constant (i.e. a number or string), it’s its own value
  • If it’s a variable name (i.e. a word, hyphenated phrase, etc.), look its value up in the dictionary
  • Parentheses? (Check if it’s one of the special cases from the next slide)
  • Otherwise it’s a function call
    • (func-expression arg-expression1arg-expressionn)
    • Execute all the subexpressions�(func-expression and arg-expression1 through arg-expressionn)
    • Call the value of func-expression, passing it the values of arg-expression1 through arg-expressionn as inputs
    • Use its output as the value of the expression

53 of 68

Special cases: Rules of computation in ISL+

If it starts with define

(define name value-expression)

  • Run value-expression
  • Assign its value to namein the dictionary

If it starts with λ or lambda:

(λ (name1namelast) result-expression)

  • Make a function
    • That names its inputs�name1namelast
    • And returns the value�of result-expression(presumably using those names)

If it starts with the the word local

(local [(define name1 value1) � …� (define namelast valuelast)]� result-expression)

  • Run the value expressions
  • Substitutes their values for their respective�names in result-expression
  • Runs the substituted result-expression
  • Returns its value

54 of 68

Grids revisited

55 of 68

How do we make a row of items?

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

56 of 68

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)))

57 of 68

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

58 of 68

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?

59 of 68

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

60 of 68

How do we make a column?

61 of 68

Making a column

;; column: image number -> image

;; Makes an stack of copies of item

(define column (λ (item count)

(iterated-above (λ (ignore) item)

count))

62 of 68

How do we make a grid?

63 of 68

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)))

64 of 68

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)))

65 of 68

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)))

66 of 68

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)))

67 of 68

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)))

68 of 68

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)))