Lecture 18 Slides - Intro to Imperative Programming

1 of 91

Lecture 18

Imperative Programming

2 of 91

Logistics and Week Ahead

For some - Ethics Module 7 - Labor (if you're not signed up for an Ethics Discussion or missed yours earlier in the quarter you need to come see me ASAP)

  • Monday - Intro to Imperative Programming
  • Wednesday - More Imperatives (Pre-Recorded + MQ13) + Tutorial 7
  • Friday - Scope (MQ 14) (Ex 6 Due)

Reminders / Announcements:

  • Q2 Grades available by Wednesday
  • Exercise 6 DOES NOT use imperatives and is in #lang htdp/isl+
  • If you wish to work with a partner** on Ex6, follow the instructions on the assignment. Sign-ups will close Tuesday at 11:59pm for partners. IF YOU PLAN TO HAVE A PARTNER DO NOT SUBMIT PRIOR TO BOTH JOINING A CANVAS GROUP.

3 of 91

The story up until now

  • Everything in your computer is data
    • Including programs
  • Data is divided into objects
  • Objects can be inside other objects
    • An album is made up of a title, artist, and genre
    • Colors inside bitmaps
  • Objects have types
    • Procedures (Functions)
    • Numbers (1 or -3.5)
    • Strings (“this is a string”, “blue”)
    • Picture/image objects (ellipses, rectangles, etc.)
    • Albums, trees, lists, etc.

4 of 91

The story up until now

  • Computation is performed using expressions
    • Expressions have (or “return”) values (i.e. outputs)
    • Computation is performed by recursively replacing expressions with their values
  • A computation's only output is its return value
    • It's return value only depends on:
      • Its inputs
      • The expression's structure
      • The other definitions in the program
    • It doesn't depend on what was computed before unless it's directly nested/chained/connected to it
  • Once we define a variable, it's been impossible to update it

5 of 91

Change and effect

  • But some expressions don't return values
    • (define name value) causes a variable be defined
    • (require module) causes a bunch of functions to become defined
    • (define-struct type (properties…)) causes a new type be defined via some automatically defined functions.
  • These are examples of expressions we run not because they return values
    • But because they do things
    • They change the computer

  • These changes are called side effects, or just effects
  • What it really means is some change caused by the expression

6 of 91

Calling functions for their effects

  • You can write functions that make a wide range of changes in the computer
    • Changing a variable's value (assignment)
    • Changing a data object (mutation)
    • Creating files
    • Creating windows
    • Performing input or output
  • Commands that change the computer this way are called imperatives
  • As with everything else in this class, complex effects
    • Are ultimately built up from a few kinds of simple effects
    • And methods for combining them

7 of 91

Imperative programming

8 of 91

Functional vs Imperative Programming

  • Functional programming is programming without effects and sequencing
    • The only effects (output) of an expression is its return value
    • Value of a function call is determined entirely by the inputs to a function which might include nested function calls
    • Result doesn't depend on order of execution of subexpressions; the substitution model perfectly emulates execution.
  • Imperative programming
    • Expressions can have many different effects: return value, changing variables, deleting files, etc.
    • Those side effects can influence the behavior of other expressions (even if they seem unrelated).
    • Computation is achieved by sequencing changes
    • Forces us to think about execution as changes and causality

9 of 91

Advantages of imperative programming

  • Imperative programs can be more efficient than functional programs
    • Because the low-level hardware is ultimately representing the code as imperatives (you'll learn more about this in CS 213).
  • Simpler for some application domains
    • Simulations: what you're computing is just a series of changes (e.g. video games)
    • Random numbers: if your random number generator always returns the same value…
    • Other applications where the task definition involves change

10 of 91

#lang htdp/asl

All the code for the rest of the quarter will be in the Advanced Student Language with the exception of Ex.6

11 of 91

Effects in imperative programs

  • An imperative might produce an output
  • But it also has an effect on the computer
    • i.e. changes memory
    • Also known as a “side effect
  • It’s very important to make the effects of an imperative clear to a human reader
    • Or you can get heinous bugs (in fact, this is one of key reasons we start with functional programming)

12 of 91

Effects in imperative programs

  • So in addition to a
    • Type signature
    • Purpose statement
  • We’ll also give one or more effect statements
  • And we’ll also adopt a style convention that says that functions with side-effects are marked with a ! at the end of their names

;; make-window!: string -> window

;; Make a new window

;; Effect: creates a new window

;; on the screen

(define (make-window! title)

… some magic code …)

13 of 91

Types and Type Signatures in imperative programs

  • It’s now possible to have functions that
    • Take no inputs
    • And/or generate no outputs
  • So we need type signature notations for these

-> number�-> string

  • Means a function that takes no inputs and returns a number, string, etc.

number -> void�string -> void

  • Means a function that takes a number and returns no output

14 of 91

Primitive imperatives

15 of 91

The simplest possible imperative

; void : -> void�

(void)

  • Sometimes, you need a function that literally does nothing
    • No inputs
    • No outputs
    • No effects
  • It’s just a placeholder.
  • Most of the time, we use it to indicate a function returns no value and is instead being run for its side-effects

16 of 91

Assignment statements

(set! name new-value)

The next simplest imperative is assignment (set!) often read "set bang"

  • After execution, the variable name is changed to have the value new-value
  • Variable must have already been “created” using define
  • This is a special form. It has no return value (i.e. (void))

17 of 91

Why is this different from define?

  • You use define to make new variables
    • Can't be used inside function definitions except…
    • By putting it inside local to make new local variable
    • It doesn't change the existing global variable
  • You use set! to change an existing variable's value, be it a local or global variable, while the program is running
    • Safe to use inside a function

18 of 91

Changing a global variable

(define count 0)

(define (increment!)

(set! count

(+ count 1)))

(define (clear!)

(set! count

0))

> count

0

> (increment!)

(void)

; means no value returned

> count

1

> (clear!)

(void)

> count

0

19 of 91

Composing imperatives

20 of 91

Composing imperatives

  • Changes are most useful when we can chain them together
  • So we need mechanisms for composing imperatives
    • Do several imperatives in sequence
    • Do imperatives repeatedly (looping)

21 of 91

Sequencing imperatives

22 of 91

Sequencing with begin

(begin expression-1 expression-2)

  • Runs expressions in sequence
  • Returns the value of the last expression automatically
  • Equivalent of { }’s in Java, C++, etc.

23 of 91

Changing a global variable and returning a value

(define count 0)

(define (increment!)

(begin (set! count

(+ count 1))

count))

(define (clear!)

(begin (set! count

0)

count))

> count

0

> (increment!)

1

> count

1

> (clear!)

0

> count

0

24 of 91

Looping imperatives

25 of 91

Summing a list in imperative form

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

26 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

27 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

0

28 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

0

remaining

'(1 2 3 4)

29 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

0

remaining

'(1 2 3 4)

loop

(λ () …)

30 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

0

remaining

'(1 2 3 4)

loop

(λ () …)

31 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

0

remaining

'(1 2 3 4)

loop

(λ () …)

32 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

1

remaining

'(1 2 3 4)

loop

(λ () …)

33 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

1

remaining

'(2 3 4)

loop

(λ () …)

34 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

1

remaining

'(2 3 4)

loop

(λ () …)

35 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

1

remaining

'(2 3 4)

loop

(λ () …)

36 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

3

remaining

'(2 3 4)

loop

(λ () …)

37 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

3

remaining

'(3 4)

loop

(λ () …)

38 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

3

remaining

'(3 4)

loop

(λ () …)

39 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

3

remaining

'(3 4)

loop

(λ () …)

40 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

6

remaining

'(3 4)

loop

(λ () …)

41 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

6

remaining

'(4)

loop

(λ () …)

42 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

6

remaining

'(4)

loop

(λ () …)

43 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

6

remaining

'(4)

loop

(λ () …)

44 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

10

remaining

'(4)

loop

(λ () …)

45 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

10

remaining

'()

loop

(λ () …)

46 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

10

remaining

'()

loop

(λ () …)

47 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

10

remaining

'()

loop

(λ () …)

48 of 91

(sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! sum

(+ sum (first remaining)))

(set! remaining

(rest remaining))

(loop))))]

(loop)))

Variable

Value

lst

'(1 2 3 4)

sum

10

remaining

'()

loop

(λ () …)

49 of 91

Imperative bugs

50 of 91

Imperatives can be tricky

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

51 of 91

Imperatives can be tricky

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

first: expects a non-empty list; given: '()

52 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

53 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

0

54 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

0

remaining

'(1 2 3 4)

55 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

0

remaining

'(1 2 3 4)

loop

(λ () …)

56 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

0

remaining

'(1 2 3 4)

loop

(λ () …)

57 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

0

remaining

'(1 2 3 4)

loop

(λ () …)

58 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

0

remaining

'(2 3 4)

loop

(λ () …)

59 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

2

remaining

'(2 3 4)

loop

(λ () …)

60 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

2

remaining

'(2 3 4)

loop

(λ () …)

61 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

2

remaining

'(2 3 4)

loop

(λ () …)

62 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

2

remaining

'(3 4)

loop

(λ () …)

63 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

5

remaining

'(3 4)

loop

(λ () …)

64 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

5

remaining

'(3 4)

loop

(λ () …)

65 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

5

remaining

'(3 4)

loop

(λ () …)

66 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

5

remaining

'(4)

loop

(λ () …)

67 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

5

remaining

'(4)

loop

(λ () …)

68 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

5

remaining

'(4)

loop

(λ () …)

69 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

5

remaining

'(4)

loop

(λ () …)

70 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

5

remaining

'()

loop

(λ () …)

71 of 91

What happened?

(define (sum-list lst)

(local [(define sum 0)

(define remaining lst)

(define (loop)

(if (empty? remaining)

sum

(begin (set! remaining

(rest remaining))

(set! sum

(+ sum (first remaining)))

(loop))))]

(loop)))

(sum-list (list 1 2 3 4))

Variable

Value

lst

'(1 2 3 4)

sum

5

remaining

'()

loop

(λ () …)

72 of 91

Higher-order imperatives

73 of 91

Looping as a sequencing primitive

  • Most imperative languages have special iteration constructs
    • while
    • for
    • foreach
  • In ASL, you can just use functions
    • for-each is a useful example

(for-each func a-list)

  • Exactly like map in that it runs func repeatedly on the elements of a-list
  • But returns no value so we use it when you’re calling func as an imperative

74 of 91

Cleaning up the code

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

75 of 91

Example: (sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

76 of 91

Example: (sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

Variable

Value

lst

'(1 2 3 4)

77 of 91

Example: (sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

Variable

Value

lst

'(1 2 3 4)

sum

0

78 of 91

Example: (sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

Variable

Value

lst

'(1 2 3 4)

sum

0

79 of 91

Example: (sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

Variable

Value

lst

'(1 2 3 4)

sum

1

80 of 91

Example: (sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

Variable

Value

lst

'(1 2 3 4)

sum

3

81 of 91

Example: (sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

Variable

Value

lst

'(1 2 3 4)

sum

6

82 of 91

Example: (sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

Variable

Value

lst

'(1 2 3 4)

sum

10

83 of 91

Example: (sum-list '(1 2 3 4))

(define (sum-list lst)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum (+ sum element)))

lst)

sum)))

Variable

Value

lst

'(1 2 3 4)

sum

10

84 of 91

Comparison of�functional and imperative programming

85 of 91

sum-list in functional and imperative form

Functional version:

(define (sum-list/func a-list)

(if (empty? a-list)

0

(+ (first a-list)

(sum-list/func

(rest a-list)))))

Imperative version:

(define (sum-list a-list)

(local [(define sum 0)

(define rem a-list)

(define (loop)

(if (empty? rem)

sum

(begin (set! sum

(+ sum

(first rem)))

(set! rem

(rest rem))

(loop))))]

(loop)))

86 of 91

sum-list in functional and imperative form

Functional version:

(define (sum-list/func a-list)

(if (empty? a-list)

0

(+ (first a-list)

(sum-list/func

(rest a-list)))))

Imperative version:

(define (sum-list a-list)

(local [(define sum 0)

(define rem a-list)

(define (loop)

(if (empty? rem)

sum

(begin (set! sum

(+ sum

(first rem)))

(set! rem

(rest rem))

(loop))))]

(loop)))

More focused on what to compute

More focused on how to compute it

87 of 91

sum-list in functional and imperative form

Functional version:

(define (sum-list/func a-list)

(if (empty? a-list)

0

(+ (first a-list)

(sum-list/func

(rest a-list)))))

Imperative version:

(define (sum-list a-list)

(local [(define sum 0)]

(begin (for-each (λ (element)

(set! sum

(+ sum element)))

a-list)

sum)))

More focused on what to compute

More focused on how to compute it

88 of 91

What have we changed?

89 of 91

Rules of computation in ASL

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

90 of 91

Special cases: New Imperative Additions

If it starts with λ or lambda:

(λ (name1namelast) result-expression)

  • Make a function
    • That names its inputs in the dictionaryname1namelast
    • Returns the value�of result-expression(presumably using those names)
    • Sets the dictionary back the way it was

If it starts with the the word local

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

  • Run the value expressions
  • Assign their values to their respective�names in the dictionary
  • Substitutes their values for their respective�names in result-expression
  • Runs the substituted result-expression
  • Returns its value
  • Set the dictionary back the way it was

91 of 91

Imperative special forms

If it starts with set!

(set! name value-expression)

  • Run value-expression
  • Update the value of namein the dictionary

If it starts with the the word begin

(begin expressions )

  • Run the expressions
  • Return the value of the last one