Lecture 5
Iteration and Iterators
Logistics and Week Ahead
For some - Ethics Module 2 – Accessibility
Reminders:
Project Bullseye.
Write a function that takes as input a bullseye radius, and makes a 4-circle bullseye where the largest circle is that radius and the colors alternate between blue and green.
Project Bullseye.
;; bullseye: number -> image
;; creates a bullseye shape with the outermost circle the specified size
We'd call your function like this:
(bullseye 100)
Note on color objects
(make-color r g b)
(make-color r g b a)
(color r g b)
You can also specify a color using a color object:
What’s wrong with this?
(overlay (square 50 "solid" (color 0 250 0))
(square 100 "solid" (color 0 200 0))
(square 150 "solid" (color 0 150 0))
(square 200 "solid" (color 0 100 0))
(square 250 "solid" (color 0 50 0)))
What’s wrong with this?
(overlay (square 50 "solid" (color 0 250 0))
(square 100 "solid" (color 0 200 0))
(square 150 "solid" (color 0 150 0))
(square 200 "solid" (color 0 100 0))
(square 250 "solid" (color 0 50 0)))
It’s (almost) the same code
repeated over and over again!
It's an expression.
What’s wrong with this?
;; box: number -> image
;; makes a size x size square
(define box
(λ (size)
(square size
"solid"
(color 0
(- 300 size)
0))))
; actually make the shape
(overlay (box 50)
(box 100)
(box 150)
(box 200)
(box 250))
What’s wrong with this?
;; box: number -> image
;; makes a size x size square
(define box
(λ (size)
(square size
"solid"
(color 0
(- 300 size)
0))))
; actually make the shape
(overlay (box 50)
(box 100)
(box 150)
(box 200)
(box 250))
This has saved us some work, but doesn't save us that much trouble.
What’s wrong with this?
;; box: number -> image
;; makes a size x size square
(define box
(λ (size)
(square size
"solid"
(color 0
(- 260 size)
0))))
; draw the shape
(overlay (box 10) (box 20) (box 30) (box 40)
(box 50) (box 60) (box 70) (box 80) (box 90)
(box 100) (box 110) (box 120) (box 130) (box 140)
(box 150) (box 160) (box 170) (box 180) (box 190)
(box 200) (box 210) (box 220) (box 230) (box 240)
(box 250))
It does scale better to more boxes though!
What’s wrong with this?
;; box: number -> image
;; makes a size x size square
(define box
(λ (size)
(square size
"solid"
(color 0
(- 260 size)
0))))
; draw the shape
; what do we put here?
Imagine explaining how to make this shape to a human…
What’s wrong with this?
;; box: number -> image
;; makes a size x size square
(define box
(λ (size)
(square size
"solid"
(color 0
(- 260 size)
0))))
; draw the shape
; what do we put here?
Imagine explaining how to make this shape to a human…
Place 25 boxes on top of each other, each one bigger than the last with a slightly different color.
Good software design is about structured laziness
Iteration
Iterators
Theme and variation
image iterators
Goal: Turn the Left side into the RIght Side
(overlay (box 50)
(box 100)
(box 150)
(box 200)
(box 250))
(some-iterator (λ (some-name)
(box some-argument))
5)
higher-order functions
Higher Order Functions
Functions can return other functions
;; add: number -> (number -> number)�;; Make a function called add that �;; adds x to its input
(define add� (λ (x) � (λ (y)� (+ x y))))
Note: the return type is a function that takes a number as input and returns a number, so its type, (number -> number) has its own ->
(add 2)
> ((λ (x) (λ (y) (+ x y))) 2)
is the same thing as…
(λ (y) (+ 2 y))
is the same thing as…
A function that adds 2 to its argument
Functions can return other functions
;; add: number -> (number -> number)�;; Make a function called add that �;; adds x to its input
(define add� (λ (x) � (λ (y)� (+ x y))))
Note: the return type is a function that takes a number as input and returns a number, so its type, (number -> number) has its own ->
((add 2) 4)
(((λ (x) (λ (y) (+ x y))) 2) 4)
((λ (y) (+ 2 y)) 4)
(+ 2 4)
6
Functions can be arguments
;; squarish: picture-func -> image�;; where picture-func is�;; number number string color�;; -> image�;; Makes a square picture using �;; procedure
(define squarish� (λ (func)� (func 10
10 � "outline" � "white")))
(squarish rectangle)
((λ (func)� (func 10 10 "outline" "white")) � rectangle)
(rectangle 10 10 "outline" "white")
—---------------------------------
(squarish ellipse)
((λ (func)� (func 10 10 "outline" "white")) � ellipse)
(ellipse 10 10 "outline" "white")
Or both
(define f (my-compose squared sin))
(define f ((λ (f1 f2) � (λ (arg) � (f1 (f2 arg))))� squared� sin))
(define f ((λ (f1 f2) � (λ (arg) � (f1 (f2 arg))))� (λ (n) (* n n))� sin))
(define f (λ (arg)� ((λ (n) (* n n))� (sin arg))))
;; my-compose: (number -> number)�;; (number -> number)�;; -> (number -> number)�;; Makes a function that runs both its�;; input function
(define my-compose� (λ (f1 f2)� (λ (arg)� (f1 (f2 arg)))))
;; squared: number -> number�;; Compute the square of a number
(define squared� (λ (n)� (* n n)))
Or both
;; my-compose: (number -> number)�;; (number -> number)�;; -> (number -> number)�;; Makes a function that runs both its�;; input function
(define my-compose� (λ (f1 f2)� (λ (arg)� (f1 (f2 arg)))))
;; squared: number -> number�;; Compute the square of a number
(define squared� (λ (n)� (* n n)))
(f 0)
= ((λ (arg)
((λ (n) (* n n))(sin arg)))
0)
= ((λ (n) (* n n))
(sin 0))
= ((λ (n) (* n n))
0)
= (* 0 0)
= 0
The iterated-overlay function
;; iterated-overlay: (number -> image) number -> image
;; Makes a series of pictures using function, then overlays them.
(iterated-overlay picture-making-function count)
The iterated-overlay function & friends
;; iterated-overlay: (number -> image) number -> image
;; Makes a series of pictures using function, then overlays them.
(iterated-overlay picture-making-function count)
(iterated-underlay picture-making-function count)
(iterated-above picture-making-function count)
(iterated-beside picture-making-function count)
These functions aren’t built in
(require "iterated-images.rkt")
Semantics
(iterated-overlay func 4)
(overlay (func 0)
(func 1)
(func 2)
(func 3))
iterated-overlay example
Example
> (iterated-overlay ;; number -> image
;; makes a square rotated by n degrees
(λ (n)
(rotate n
(square 100 "outline" "blue")))
10)
>
How to read this program
> (iterated-overlay ;; number -> image
;; makes a square rotated by n degrees
(λ (n)
(rotate n
(square 100 "outline" "blue")))
10)
How to read this program
> (iterated-overlay ;; number -> image
;; makes a square rotated by n degrees
(λ (n)
(rotate n
(square 100 "outline" "blue")))
10)
How to read this program
> (iterated-overlay ;; number -> image
;; makes a square rotated by n degrees
(λ (n)
(rotate n
(square 100 "outline" "blue")))
10)
How to read this program
> (iterated-overlay ;; number -> image
;; makes a square rotated by n degrees
(λ (n)
(rotate n
(square 100 "outline" "blue")))
10)
Example
> (iterated-overlay (λ (n)
(rotate (* 36 n)
(square 100 "outline" "blue")))
10)�
>
concentric�box example
Our original example - now with iteration!
(overlay (square 50 "solid" (color 0 250 0))
(square 100 "solid" (color 0 200 0))
(square 150 "solid" (color 0 150 0))
(square 200 "solid" (color 0 100 0))
(square 250 "solid" (color 0 50 0)))
Has evolved into…
Our original example - now with iteration!
(iterated-overlay
;; number -> image
;; make a square rotated and colored
;; based on n
(λ (n)
(square (* (+ n 1)
50)
"solid"
(color 0
(- 250
(* n 50))
0)))
5)
Wait, why is that easier?
Changing the number of boxes
(overlay (square 50 "solid" (color 0 250 0))
(square 100 "solid" (color 0 200 0))
(square 150 "solid" (color 0 150 0))
(square 200 "solid" (color 0 100 0))
(square 250 "solid" (color 0 50 0))
...type more here...)
Changing the number of boxes
Rather than this…
(iterated-overlay
(λ (n)
(square (* (+ n 1)
50)
"solid"
(color 0
(- 250
(* n 50))
0)))
5)
We can do even better!
Making a function out of it
;; boxes: number -> image
;; Makes an image with a specified number of boxes
(define boxes
(λ (count)
(iterated-overlay
;; number -> image
;; make a box sized and colored based on n.
(λ (n)
(square (* (+ n 1)
(quotient 250 count))
"solid"
(color 0
(- 250
(* n
(quotient 250
count)))
0)))
count)))
Note: quotient divides two integers and rounds down
I still think it’s easier to do it by hand!
Okay, you’re probably right
but …
This is not easier to do by hand …
This is not easier to do by hand …
> (iterated-beside boxes 10)
on counting from zero
Annoying subtle point…
> (iterated-beside boxes 10)
Why are there only 9 sets of boxes?
Computers count from zero
> (beside (boxes 0) (boxes 1) (boxes 2) (boxes 3)
(boxes 4) (boxes 5) (boxes 6) (boxes 7)
(boxes 8) (boxes 9))
So the first call produces zero boxes, i.e. nothing
Computers count from zero
> (beside (boxes 0) (boxes 1) (boxes 2) (boxes 3)
(boxes 4) (boxes 5) (boxes 6) (boxes 7)
(boxes 8) (boxes 9))
This is actually useful much of the time