Lab 8:
Assignment, State and Environment
We ordinarily view the world as populated by
independent objects, each of which has a state that changes over
time. An object is said to "have state" if its behavior is
influenced by its history. A bank account, for example, has state in
that the answer to the question "Can I withdraw $100?" depends upon
the history of deposit and withdrawal transactions. We can
characterize an object's state by one or more state variables, which
among them maintain enough information about history to determine
the object's current behavior. In a simple banking system, we could
characterize the state of an account by a current balance rather
than by remembering the entire history of account transactions.
In a system composed of many objects, the objects are rarely
completely independent. Each may influence the states of others
through interactions, which serve to couple the state variables of one
object to those of other objects. Indeed, the view that a system is
composed of separate objects is most useful when the state variables
of the system can be grouped into closely coupled subsystems that are
only loosely coupled to other subsystems.
This view of a system can be a powerful framework for organizing
computational models of the system. For such a model to be modular, it
should be decomposed into computational objects that model the actual
objects in the system. Each computational object must have its own
local state variables describing the actualobject's state. Since the
states of objects in the system being modeled change over time, the
state variables of the corresponding computational objects must also
change. If we choose to model the flow of time in the system by the
elapsed time in the computer, then we must have a way to construct
computational objects whose behaviors change as our programs run. In
particular, if we wish to model state variables by ordinary symbolic
names in the programming language, then the language must provide an
assignment operator to enable us to change the value associated with a
name.
Labwork
finish this during section
Template
Type the following command at the terminal to copy the template
file to the current directory:
cp ~cs61as/autograder/templates/hw8.scm .
Exercise 1.
Given below is a simplified version of the make-account procedure on page 223 of Abelson and Sussman.
(define (make-account balance)
(define (withdraw amount)
(set! balance (- balance amount)) balance)
(define (deposit amount)
(set! balance (+ balance amount)) balance)
(define (dispatch msg)
(cond
((eq? msg 'withdraw) withdraw)
((eq? msg 'deposit) deposit) ) )
dispatch)
Fill in the blank in the following code so that the
result works exactly the same as the make-account procedure
above, that is, responds to the same messages and produces the same
return values. The differences between the two procedures are that
the inside of make-account above is enclosed in
the let below, and the names of the parameter
to make-account are different.
(define (make-account init-amount)
(let ( YOUR CODE HERE )
(define (withdraw amount)
(set! balance (- balance amount)) balance)
(define (deposit amount)
(set! balance (+ balance amount)) balance)
(define (dispatch msg)
(cond
((eq? msg 'withdraw) withdraw)
((eq? msg 'deposit) deposit) ) )
dispatch) )
Exercise 2.
Modify either version of make-account so
that, given the message balance, it returns the current
account balance, and given the
message init-balance, it returns the amount with which the
account was initially created. For example:
> (define acc (make-account 100))
acc
> (acc 'balance)
100
Exercise 3.
Modify make-account so that, given the
message transactions, it returns a list of all transactions
made since the account was opened. For example:
> (define acc (make-account 100))
acc
> ((acc 'withdraw) 50)
50
> ((acc 'deposit) 10)
60
> (acc 'transactions)
((withdraw 50) (deposit 10))
Exercise 4.
Given this definition:
(define (plus1 var)
(set! var (+ var 1))
var)
Show the result of computing
(plus1 5)
using the substitution model. That is, show the
expression that results from substituting 5 for var in the body of
plus1, and then compute the value of the resulting expression. What
is the actual result from Scheme?
Exercise 5.
This lab activity consists of example programs for you
to run in Scheme. Predict the result before you try each example. If
you don't understand what Scheme actually does, ask for help! Don't
waste your time by just typing this in without paying attention to
the results.
(define (make-adder n) ((lambda (x)
(lambda (x) (+ x n))) (let ((a 3))
(+ x a)))
(make-adder 3) 5)
((make-adder 3) 5) (define k
(let ((a 3))
(define (f x) (make-adder 3)) (lambda (x) (+ x a))))
(f 5) (k 5)
(define g (make-adder 3)) (define m
(lambda (x)
(g 5) (let ((a 3))
(+ x a))))
(define (make-funny-adder n)
(lambda (x) (m 5)
(if (equal? x 'new)
(set! n (+ n 1)) (define p
(+ x n)))) (let ((a 3))
(lambda (x)
(define h (make-funny-adder 3)) (if (equal? x 'new)
(set! a (+ a 1))
(define j (make-funny-adder 7)) (+ x a)))))
(h 5) (p 5)
(h 5) (p 5)
(h 'new) (p 'new)
(h 5) (p 5)
(j 5) (define r
(lambda (x)
(let ((a 3)) (let ((a 3))
(+ 5 a)) (if (equal? x 'new)
(set! a (+ a 1))
(let ((a 3)) (+ x a)))))
(lambda (x) (+ x a)))
(r 5)
((let ((a 3))
(lambda (x) (+ x a))) (r 5)
5)
(r 'new)
(r 5)
(define s (define (ask obj msg . args)
(let ((a 3)) (apply (obj msg) args))
(lambda (msg)
(cond ((equal? msg 'new) (ask s 'add 5)
(lambda ()
(set! a (+ a 1)))) (ask s 'new)
((equal? msg 'add)
(lambda (x) (+ x a))) (ask s 'add 5)
(else (error "huh?"))))))
(define x 5)
(s 'add)
(let ((x 10)
(s 'add 5) (f (lambda (y) (+ x y))))
(f 7))
((s 'add) 5)
(define x 5)
(s 'new)
((s 'add) 5)
((s 'new))
((s 'add) 5)