- By
**jatin** - Follow User

- 131 Views
- Uploaded on

Download Presentation
## PowerPoint Slideshow about 'Imperative Programming Chapter 6' - jatin

Download Now**An Image/Link below is provided (as is) to download presentation**

Download Now

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript

Local State

Real world software like:

- Banks
- Course grading system

Are state systems. i.e. they change along time: for example: current balance and current grade.

What is Imperative Programming?

“In computer science, imperative programming is a programming paradigm that describes computation in terms of statements that change a program state (Wikipedia)”

Not better the FP! Just different

The Imperative Programming Model

- Imperative programming is characterized by:
- Understanding variables as storage places (addresses)
- Mutation operations
- Operational semantics

Mutation in Racket

- Variable assignment: set!
- Box type
- Mutable data types (we will not use Racket’s built in, but create our own)

Variable Assignment

Modification of value of a defined variable

> (define my-list (list 1 2 3))

> my-list

’(1 2 3)

> (set! my-list (list 1 2 4))

> my-list

’(1 2 4)

> (set! a 4)

. . set!: assignment disallowed;

cannot set variable before its definition

The Box Type

Values are references (or pointers) for values that can be changed during computation.

- Constructor: box
- Selector: unbox
- Mutator: set-box!

Box Examples (1)

(define a (box 7))

> (* 6 (unbox a))

42

> a

'#&7

> (set-box! a (+ (unbox a) 3))

> (* 6 (unbox a))

60

Box Example (2):

> (definecirc-l (list (box 1) (box 2) (box 3)))

> circ-l

'(#&1 #&2 #&3)

> (unbox (car circ-l))

1

> (unbox (cadr circ-l))

2

> (unbox (caddr circ-l))

3

> (set-box! (caddr circ-l) circ-l)

> circ-l

#0='(#&1 #&2 #�#)

> (unbox (caddr circ-l))

#0='(#&1 #&2 #�#)

> (eq? circ-l (unbox (caddr circ-l)))

#t

The Box type

The Box type: Type constructor: BOX(T )

procedure type name

Value constructor: box [T → BOX(T )]

Selector: unbox [BOX(T ) → T]

Mutator: set-box! [BOX(T ) → Void]

Identiﬁer: box? [T → Boolean]

Value equality: equal? [T1 ∗ T2 → Boolean]

Identity equality: eq? [T1 ∗ T2 → Boolean]

Side Effects

- Side effects are "non-functional"There existence does not agree with the FP paradigm
- set! and set-box! are side eﬀects procedure
- We have already seen two kinds of side eﬀect procedures: define and the display procedure.
- Side eﬀects procedures are applied for the sake of their side eﬀects, and not for their returned value, void
- In imperative programming, it is meaningful to use sequences of expressions

State based modeling

- Defining objects with a modifiable private fields (local variables), and a set of accessors (selectors and mutators) that have controlled access to the object's private fields.
- All objects may have access to shared (static) variables.

Bank Account Withdrawal Example

;; Signature: withdraw(amount)

;; Purpose: Withdraw ’amount’ from a private ’balance’.

;; Type: [Number -> Number]

;; Post-condition: result = if balance@pre >= amount

;; then balance@pre - amount

;; else balance

(define withdraw

(let ((balance 100))

(lambda (amount)

(if (>= balance amount)

(begin (set!

balance

(- balance amount))

balance)

(begin (display "Insufficient funds")

(newline)

balance)))))

#<procedure:withdraw>

> (withdraw 25)

75

> (withdraw 25)

50

> (withdraw 60)

Insufficient funds

50

> (withdraw 15)

35

(define withdraw

(let ((balance 100))

(lambda (amount)

(if (>= balance amount)

(begin (set!

balance

(-

balance

amount))

balance)

(begin (display

"Insufficient funds")

(newline)

balance)))))

Full Bank Account Example

;; Signature: make-account(balance)

;; Type: [Number -> [Symbol -> [Number -> Number]]]

(define make-account

(λ (balance)

(let ((balance balance))

(letrec

((get-balance (λ (amount) balance))

(set-balance! (λ (amount) (set! balance amount)))

(withdraw (λ (amount)

(if (>= balance amount)

(begin (set-balance! (- balance amount))

balance)

(begin (display "Insufficient funds")

(newline)

balance))))

(deposit (λ (amount)

(set-balance! (+ balance amount))

balance))

(dispatch (λ (m)

(cond ((eq? m ’balance) get-balance)

((eq? m ’withdraw) withdraw)

((eq? m ’deposit) deposit)

(else (error

’make-account

"Unknown request: ~s" m))))))

dispatch))))

> (define acc (make-account 100))

> acc

#<procedure:dispatch>

> ((acc ’withdraw) 50)

50

> ((acc ’withdraw) 60)

Insufficient funds

50

> ((acc ’withdraw) 30)

20

> ((acc ’withdraw) 60)

Insufficient funds

20

> (define acc2 (make-account 100))

> ((acc2 ’withdraw) 30)

70

> ((acc ’withdraw) 30)

Insufficient funds

20

Mutable ADTs : Pair

; Type: [T1*T2 -> [Symbol -> Procedure]]

; The dispatch procedure returns procedures with different arities

; (Currying could help here).

(define mpair

(λ (x y)

(letrec ((get-x (λ () x))

(get-y (λ () y))

(set-x! (λ (v)

(set! x v)))

(set-y! (λ (v)

(set! y v)))

(dispatch

(lambda (m)

(cond ((eq? m 'car) get-x)

((eq? m 'cdr) get-y)

((eq? m 'set-car!) set-x!)

((eq? m 'set-cdr!) set-y!)

(else (error

'mpair

"Undefined operation ~s"

m))))))

dispatch)))

Mutable ADTs : Pair

(define mutable-car

(λ (z)

((z ’car))))

(define mutable-cdr

(λ (z)

((z ’cdr))))

(define set-car!

(lambda (z new-value)

((z ’set-car!) new-value)))

(define set-cdr!

(lambda (z new-value)

((z ’set-cdr!) new-value)))

Mutable ADTs : Pair

> (define p1 (mpair 1 2))

> (mutable-car p1)

1

> (mutable-cdr p1)

2

> (set-car! p1 3)

> (mutable-car p1)

3

> (set-cdr! p1 4)

> (mutable-cdr p1)

4

> (mutable-cdr (set-cdr! p1 5))

. . procedure application: expected procedure, given: #<void>; arguments were: ’cdr

Lazy Pair

(define lazy-mpair

(λ (x y)

(let ((x (box x))

(y (box y)))

(λ (sel)

(sel x y)))))

(define lazy-mcar

(λ (z)

(z (λ (x y)

(unbox x)))))

(define lazy-mcdr

(λ (z)

(z (λ (x y)

(unbox y)))))

(define lazy-set-car!

(λ (z new-value)

(z (λ (x y)

(set-box!

x

new-value)))))

(define lazy-set-cdr!

(λ (z new-value)

(z (λ (x y)

(set-box!

y

new-value)))))

Lazy Pair

> (define p2 (lazy-mpair 1 2))

> (lazy-mcar p2)

1

> (lazy-mcdr p2)

2

> (lazy-set-car! p2 3)

> (lazy-mcar p2)

3

Value Equality vs. Identity Equality

Since we have states, we can check state equality or identity.

- equal? – State (value) equality
- eq? – Object equality

Value Equality vs. Identity Equality

> (define x (list (box 'a) (box 'b)))

> (define y (list (car x) (box 'c) (box 'd)))

> (define z (list (box 'a) (box 'c) (box 'd)) )

> (define w y)

> (eq? y w) ; identity

#t

> (eq? y z)

#f

> (equal? y z) ; value equality

#t

> (equal? (car z) (car x))

#t

> (eq? (car z) (car x))

#f

Evaluation of letrec

Recall the problem we had:

(define fact

(lambda (n)

(let ((iter

(lambda (c p)

(if

(= c 0)

p

(iter

(- c 1)

(* c p))))))

(iter n 1))))

Recursion call will not work

Evaluation of letrec

Here’s a solution using imperative programming:

(define fact

(lambda (n)

(let ((iter‘unassigned))

(set!iter

(lambda (c p)

(if

(= c 0)

p

(iter

(- c 1)

(* c p)))))

(iter n 1))))

Now iter is in the scope

Evaluation of letrec

- Now we unveil the secret of letrec…
- Its semantics cannot be explained in FP

(let ((f1 ’unassigned) ... (fn ’unassigned))

(set! f1 lambda-exp1)

...

(set! fn lambda-expn)

e1 ... em))

Extending the Environment Model

- The substitution model cannot support mutation
- Semantics ofset-binding!(x,val,<f1,...,fn>) :

Extending the Environment Model

- Add set! Special operator:

env−eval[(set! x e),env] =

set−binding!(x,env−eval[e,env],env)

- Add Box type

Extending the Interpreter & Analyzer:Data Structures

(define set-binding-in-env!

(lambda (envvarval)

(letrec ((defined-in-env

(lambda (varenv)

(if (empty-env? env)

env

(let ((b (get-value-of-variable

(first-frame env)

var)))

(if (eq? b '_not-found)

(defined-in-envvar (enclosing-envenv))

(first-boxed-frame env)))))))

(let ((boxed-frame (defined-in-envvarenv)))

(if (empty? boxed-frame)

(error 'set! "variable not found")

(let ((frame (unbox boxed-frame)))

(set-box!

boxed-frame

(change-frame (make-binding varval) frame))))))))

Recursive call

Creates a new frame by adding a new binding

Extending the Interpreter & Analyzer: Data Structures

(define change-frame

(lambda (binding frame)

(let ((bvar (binding-variable binding))

(bval (binding-value binding)))

(change-sub frame bvarbval))))

(define change-sub

(lambda (sub var value)

(let ((vars (get-variables sub))

(values (get-values sub)))

(if (member varvars)

(make-sub

(cons varvars)

(cons value values))

(error

'change-sub

"substitution is not defined on variable")))))

Extending the Interpreter & Analyzer: Data Structures

(define make-the-global-environment

(lambda ()

(let* ((primitive-procedures

(list (list 'car car) (list 'cdrcdr)

...

(list 'box box)

(list 'unboxunbox)

(list 'box? box?)

(list 'set-box! set-box!)...

Extending the Interpreter & Analyzer:ASP

(define letrec->let

(lambda (exp)

(letrec ((make-body

(lambda (varsvals)

(if (null? vars)

(letrec-body exp)

(make-sequence

(make-assignment

(car vars)

(car vals))

(make-body

(cdrvars)

(cdrvals))))))

(make-bindings

(lambda (vars)

(map

(lambda (var)

(list var ’unassigned))

vars))))

(let* ((vars (letrec-variables exp))

(vals (letrec-initial-values exp))

)

(make-let

(make-bindings vars)

(make-body varsvals))))))

(define make-sequence

(lambda (exp1 exp2)

(cons exp1 exp2)))

(define make-assignment

(lambda (variable value)

(attach-tag (list variable value) 'set!)))

Recursive call

Extending the Interpreter: env-eval

(define eval-special-form

(lambda (exp env)

(cond

...

((assignment? exp)

(eval-assignment exp env)))))

(define eval-assignment

(lambda (exp env)

(set-binding-in-env!

env

(assignment-variable exp)

(env-eval (assignment-value exp) env))

'ok))

Extending the Analyzer

(define analyze-assignment

(lambda (exp)

(let ((var (assignment-variable exp))

(val (analyze (assignment-value exp))))

(lambda (env)

(set-binding-in-env! envvar (valenv))

’ok))))

Type Checking

- (set! x e) is well typed if e is well typed
- Typing rule for set! :

For every: type assignment TA,

expression e, and

type expression S:

If Tenv|- e:S,

Tenv|- x:S,

Then Tenv |- (set! x e):Void

Type Checking

- Axiom for box

For every type environment Tenv and type expression S:

Tenv|- box:[S -> BOX(S)]

Tenv|- unbox:[BOX(S) -> S]

Tenv|- set-box!:[BOX(S)*S -> Void]

Tenv|- box?:[S -> Boolean]

Tenv|- equal?:[BOX(S)*BOX(S) -> Boolean]

Tenv|- eq?:[BOX(S)*BOX(S) -> Boolean]

Course summary 1/3

General concepts:

- semantics, types
- syntax, CFG(BNF),
- operational semantics, static analysis, renaming, substitution, interpretation(evaluation)
- polymorphic types, type safety

Course summary 2/3

functional programming model

- function definition and application
- special forms
- derived expressions, ASP
- apply-procedure, environments, analysis
- high-order procedures
- variable binding, lexical scoping (dynamic scoping)
- static type inference
- pattern matching

Course summary 3/3

logic programming model

- axioms and queries
- proof trees, unification, pruning

imperative programming

- mutable data types
- state based execution of assignments
- local state encapsulation

Techniques:

CPS, ADTs, Currying , Sequences, lazy lists

Download Presentation

Connecting to Server..