Chapter 3: Modularity, Objects, and State so far we have reviewed the primitive elements of how programs are made and how those primitive elements can be combined in complex ways. we learned the value of abstraction and modular programs. - modular :: the nature of a program thot it can be divided "naturally" into coherent parts that can be separately developed and maintained we now look towards how to design entire systems. we will look at two prominent strategies for program construction: - objects :: seeing a program as a collection of distinct objects whose behaviors may change over time - streams :: seeing a program as a flow of information in a system we will finally discard the substitution model of chapter 1 in favor of the environment model * 3.1 assignment and local state we ordinarily view the world as a collection of independent objects each of which has state that changes over time. at this point (in ch 3!!!) we will discuss local state variables and the assignment operator ** 3.1.1 local state variables we now have a comptational object with time-varying state this means: : (withdraw 25) --> 75 : (withdraw 25) --> 25 : (withdraw 60) --> "Insufficient Funds" : (withdraw 15) --> 35 these are not pure funtions when evaluated twice, they yield different results this is /new/ before, we computed mathematical functions #+BEGIN_SRC scheme (define balance 100) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient Funds")) #+END_SRC we have the new language features, set! which sets a new value to a variable: : (set! name new-value) and we have the (begin ... ... ...) form, which returns the value of its final expression there's some trouble with that begin variable. we can make it internal by encapsulating it: #+BEGIN_SRC scheme (define new-withdraw (let ((balance 100)) (lambda (amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient Funds")))) #+END_SRC combining set! with local variables is the general technique for constructing computational objects. --> here we have just annhialated our substitution model. according to it, the above is incomprehensible. we will address later. first, a few variations on this new and very exciting theme #+BEGIN_SRC scheme :session mw (define (make-withdraw balance) (lambda (amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient Funds"))) #+END_SRC #+RESULTS: : make-withdraw which can be used to make accounts with custom amounts #+BEGIN_SRC scheme :session mw (define W1 (make-withdraw 100)) (define W2 (make-withdraw 100)) (W1 50) (W2 70) #+END_SRC #+RESULTS: : 30 these two withdrawal accounts are independent of each other to make a functional bank account: #+BEGIN_SRC scheme :session bank (define (make-account balance) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient Funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (define (dispatch m) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) (else (error "Unknown request -- MAKE-ACCOUNT" m)))) dispatch) #+END_SRC #+RESULTS: : make-account and to use it: #+BEGIN_SRC scheme :session bank (define acc (make-account 100)) ((acc 'withdraw) 25) ((acc 'withdraw) 80) ((acc 'deposit) 120) ((acc 'withdraw) 60) #+END_SRC #+RESULTS: : 135 and: #+BEGIN_SRC scheme :session bank (define acc2 (make-account 100)) #+END_SRC #+RESULTS: : acc2 will be a completely different account ** 3.1.2 the benefits of introducing assignment with assignment, we can encapsulate state, rather than injecting it via formal parameters all over the place. ** 3.1.3 the costs of introducing assignment set! is cool, but it breaks the substitution model. it breaks all "nice" mathematical models. the reason it doesnt work is variable scope. like closures, i think. or like the kind of closure this book said is the wrong thing. - functional programming :: as we did in the first two chapters of the book, to not use assignment - imperative programming :: makes extensive use of assignment SAMENESS AND CHANGE - referentially transparent :: "equals can be substituted for equals" without changing the value of an expression set! violates referential transparency.