1
Structure and
Interpretation of Computer
Programs
Modularity, Objects, and State (part 1)
Abelson & Sussman2
UC San Diego
CSE 294
May 11, 2011
Barry Demchak
Agenda
 Functional vs Imperative languages
 OOP in Functional languages (e.g., Clojure)
 Data Encapsulation case studies
 Simple mutability (persistence)
 A simple object
 Mutability support
 Failings of the substitution model
 The environment model
 Method dispatch
 Language comparisons 2
Functional vs Imperative (1/2)
 Programming without any use of assignments
… is … known as functional programming.p230
 Looping via recursion
 Higher order programming
 Repeatable function execution  memoization
 Fewer special forms
 Programming that makes extensive use of
assignment is … imperative programming.p234
 Explicit control structures and special forms
 Introduces significant data dependency
3
Functional vs Imperative (2/2)
 Java/C++/Pascal
int factAnswer = 1;
for (int counter = 2; counter <= n; counter++)
factAnswer = factAnswer * counter;
Maps directly to registers and compare/jump
 Lisp/Clojure
(defn factorial [n]
(if (<= n 1)
1
(* n (factorial (dec n)))))
Maps to recurrence relation
4
Agenda
 Functional vs Imperative languages
 OOP in Functional languages (e.g., Clojure)
 Data Encapsulation case studies
 Simple mutability (persistence)
 A simple object
 Mutability support
 Failings of the substitution model
 The environment model
 Method dispatch
 Language comparisons 5
Object Oriented Programming
 Major properties
 Abstraction
 Inheritance
 Polymorphism
 Data encapsulation
 Major uses
 Manage complexity
 Multiple instances of stateful entities
 Orchestration of stateful entities
 Key point: Stateful entities change over time 6
Functional Programming vs OOP
 Contradiction
 Repeatable execution requires immutability
 Substitution model
(defn factorial [n]
(if (<= n 1)
1
(* n (factorial (dec n)))))
 (factorial 3)
 (* 3 (factorial 2))
 (* 3 (* 2 (factorial 1)))
 (* 3 (* 2 (* 1 1)))
 OOP depends on mutability
7
Agenda
 Functional vs Imperative languages
 OOP in Functional languages (e.g., Clojure)
 Data Encapsulation case studies
 Simple mutability (persistence)
 A simple object
 Mutability support
 Failings of the substitution model
 The environment model
 Method dispatch
 Language comparisons 8
Bringing OOP to Functional
 Abstraction (as seen by Valentin)
 Inheritance
 Polymorphism
 Data Encapsulation …implies mutable state
 Suppose a min() function
(defn min [x y]
(if (<= x y) x y))
where (min 5 6) -> 5
(min 5 6) -> 5
…
 Define last-min() to return last min() calculated
9
Simple Persistence
 Global persistence
(def last-min (atom 0))
(defn min [x y]
(reset! last-min
(if (<= x y)
x
y)))
10
 No encapsulation
 Single instance
only
 (reset!
<name> <value>)
 (swap!
<name> <func>)
(defn min-obj [init-min]
(let [last-min (atom init-min)]
(defn do-min [x y]
(reset! last-min (if (<= x y) x y)))
(defn get-last [] (deref last-min))
{:get #(get-last)
:min #(do-min %1 %2)}))
A Min Object
11
http://thinkrelevance.com/blog/2009/08/12/rifle-oriented-programming-with-clojure-2.html
A Min Object
12
(defn min-obj [init-min]
(let [last-min (atom init-min)]
(defn do-min [x y]
(reset! last-min (if (<= x y) x y)))
(defn get-last [] (deref last-min))
{:get #(get-last)
:min #(do-min %1 %2)}))
(define min1 (min-obj 1000000))  Constructor
A Min Object
13
(defn min-obj [init-min]
(let [last-min (atom init-min)]
(defn do-min [x y]
(reset! last-min (if (<= x y) x y)))
(defn get-last [] (deref last-min))
{:get #(get-last)
:min #(do-min %1 %2)}))
(define min1 (min-obj 1000000))
((min1 :min) 5 6)  Call to min()
A Min Object
14
(defn min-obj [init-min]
(let [last-min (atom init-min)]
(defn do-min [x y]
(reset! last-min (if (<= x y) x y)))
(defn get-last [] (deref last-min))
{:get #(get-last)
:min #(do-min %1 %2)}))
(define min1 (min-obj 1000000))
((min1 :min) 5 6)
((min1 :get))  Fetch last min
Agenda
 Functional vs Imperative languages
 OOP in Functional languages (e.g., Clojure)
 Data Encapsulation case studies
 Simple mutability (persistence)
 A simple object
 Mutability support
 Failings of the substitution model
 The environment model
 Method dispatch
 Language comparisons 15
(defn min-obj [init-min]
(let [last-min (atom init-min)]
(defn do-min [x y]
(reset! last-min (if (<= x y) x y)))
(defn get-last [] (deref last-min))
{:get #(get-last)
:min #(do-min %1 %2)}))
(define min1 (min-obj 1000000))
((min1 :get))
The Problem: Binding last-min
16
The Solution: Environments
17
Global environment
min:
other variables
parameters: x y
body: (if …)
(defn min [x y] (if (<= x y) x y))
 What happens when you define min():
The Solution: Environments
18
Global environment
min:
other variables
parameters: x y
body: (if …)
(defn min [x y] (if (<= x y) x y))
 What happens when you define min():
Simple Execution
19
 What happens when you execute min():
Global environment
min:
other variables
parameters: x y
body: (if …)
(min 5 6)
E1 environment
x: 5
y: 6
(if …)
Simple Execution
20
 What happens when you execute min():
Global environment
min:
other variables
parameters: x y
body: (if …)
(min 5 6)
E1 environment
x: 5
y: 6
(if …)
Variable
references
resolved by
traversing
environment
chain
(defn min-obj [init-min]
(let [last-min (atom init-min)]
(defn do-min [x y]
(reset! last-min (if (<= x y) x y)))
(defn get-last [] (deref last-min))
{:get #(get-last)
:min #(do-min %1 %2)}))
(define min1 (min-obj 1000000))
((min1 :get))
How Does min-obj Get Defined?
21
Object Definition
22
Global environment
min-obj:
other variables
parameters: init-min
body: (let [... )
(defn min-obj [init-min] (let [...))
 What happens when you define min-obj():
Object Instantiation
23
 How do you instantiate min-obj():
Global environment
min-obj:
other variables
parameters: init-min
body: (let [... )
(def min1 (min-obj 1000000))
min1:
parameters:
body: (:get #(…),
:min #(…))
last-min: 1000000
do-min:
get-last:
Environment E1
parameters: x y
body: (reset! …)
parameters:
body: (deref …)
Object Instantiation
24
 How do you instantiate min-obj():
Global environment
min-obj:
other variables
parameters: init-min
body: (let [... )
(def min1 (min-obj 1000000))
min1:
parameters:
body: (:get #(…),
:min #(…))
last-min: 1000000
do-min:
get-last:
Environment E1
parameters: x y
body: (reset! …)
parameters:
body: (deref …)
Method Execution
25
 How do you execute min():
Global environment
min-obj:
other variables
parameters: init-min
body: (let [...)
((min1 :min) 5 6)
min1:
parameters:
body: (:get #(…),
:min #(…))
last-min: 1000000
do-min:
get-last:
Environment E1
parameters: x y
body: (reset! …)
parameters:
body: (deref ...)
E2
x: 5
y: 6
Functional Language OOP
 Data encapsulation as a result of
 Constructor parameter accessible only within
function
 Binding of internal functions to constructor
parameter allows state retention
 Other points
 Dismantling of environments amenable to
access count tracking
 Dispatcher can operate on any criteria, and is
pre-wired for SOA-style message passing
26
Future Investigation
 How to subclass
 How inheritance works
 Existing (or desirable) object frameworks
 Why isn’t OOP very common in Clojure?
27
Agenda
 Functional vs Imperative languages
 OOP in Functional languages (e.g., Clojure)
 Data Encapsulation case studies
 Simple mutability (persistence)
 A simple object
 Mutability support
 Failings of the substitution model
 The environment model
 Method dispatch
 Language comparisons 28
Selected Comparisons
Deep Static
Scope
Data
Encapsulation
Clojure/Lisp Arbitrary depth Yes
Pascal Arbitrary depth Yes, but no
instances
Java/C++ No Yes
29
Data Encapsulation Comparison
(defn min-obj [init-min]
(let [last-min (atom init-min)]
(defn do-min [x y]
(reset! last-min
(if (<= x y)
x
y)))
(defn get-last []
(deref last-min))
{:get #(get-last)
:min #(do-min %1 %2)}))
(define min1 (min-obj 1000000))
((min1 :min) 5 6)
((min1 :get)) 30
class min_obj {
private int last_min;
public min_obj(int init_min) {
last_min = init_min;}
public int min(int x, int y) {
last_min = (x <= y ? x : y);
return last_min;
}
public int get () {
return last_min;}
}
min_obj a = new min_obj(1000000);
a.min(5, 6);
a.get();
Clojure Java
Static Scoping in Pascal
program test;
var a : integer;
procedure outer();
var b : integer;
procedure inner();
var c : integer;
begin
c := a + b;
end;
begin
b := a;
inner();
end;
begin
a := 0;
outer();
end.
31
Evaluation
Stack
a
prev-frame-ptr
b
prev-frame-ptr
c
prev-frame-ptr
Compiler
knows stack
location of all
variables in
scope – no
traversing
Agenda
 Functional vs Imperative languages
 OOP in Functional languages (e.g., Clojure)
 Data Encapsulation case studies
 Simple mutability (persistence)
 A simple object
 Mutability support
 Failings of the substitution model
 The environment model
 Method dispatch
 Language comparisons 32
33
Questions

Structure and interpretation of computer programs modularity, objects, and state (part 1)

  • 1.
    1 Structure and Interpretation ofComputer Programs Modularity, Objects, and State (part 1) Abelson & Sussman2 UC San Diego CSE 294 May 11, 2011 Barry Demchak
  • 2.
    Agenda  Functional vsImperative languages  OOP in Functional languages (e.g., Clojure)  Data Encapsulation case studies  Simple mutability (persistence)  A simple object  Mutability support  Failings of the substitution model  The environment model  Method dispatch  Language comparisons 2
  • 3.
    Functional vs Imperative(1/2)  Programming without any use of assignments … is … known as functional programming.p230  Looping via recursion  Higher order programming  Repeatable function execution  memoization  Fewer special forms  Programming that makes extensive use of assignment is … imperative programming.p234  Explicit control structures and special forms  Introduces significant data dependency 3
  • 4.
    Functional vs Imperative(2/2)  Java/C++/Pascal int factAnswer = 1; for (int counter = 2; counter <= n; counter++) factAnswer = factAnswer * counter; Maps directly to registers and compare/jump  Lisp/Clojure (defn factorial [n] (if (<= n 1) 1 (* n (factorial (dec n))))) Maps to recurrence relation 4
  • 5.
    Agenda  Functional vsImperative languages  OOP in Functional languages (e.g., Clojure)  Data Encapsulation case studies  Simple mutability (persistence)  A simple object  Mutability support  Failings of the substitution model  The environment model  Method dispatch  Language comparisons 5
  • 6.
    Object Oriented Programming Major properties  Abstraction  Inheritance  Polymorphism  Data encapsulation  Major uses  Manage complexity  Multiple instances of stateful entities  Orchestration of stateful entities  Key point: Stateful entities change over time 6
  • 7.
    Functional Programming vsOOP  Contradiction  Repeatable execution requires immutability  Substitution model (defn factorial [n] (if (<= n 1) 1 (* n (factorial (dec n)))))  (factorial 3)  (* 3 (factorial 2))  (* 3 (* 2 (factorial 1)))  (* 3 (* 2 (* 1 1)))  OOP depends on mutability 7
  • 8.
    Agenda  Functional vsImperative languages  OOP in Functional languages (e.g., Clojure)  Data Encapsulation case studies  Simple mutability (persistence)  A simple object  Mutability support  Failings of the substitution model  The environment model  Method dispatch  Language comparisons 8
  • 9.
    Bringing OOP toFunctional  Abstraction (as seen by Valentin)  Inheritance  Polymorphism  Data Encapsulation …implies mutable state  Suppose a min() function (defn min [x y] (if (<= x y) x y)) where (min 5 6) -> 5 (min 5 6) -> 5 …  Define last-min() to return last min() calculated 9
  • 10.
    Simple Persistence  Globalpersistence (def last-min (atom 0)) (defn min [x y] (reset! last-min (if (<= x y) x y))) 10  No encapsulation  Single instance only  (reset! <name> <value>)  (swap! <name> <func>)
  • 11.
    (defn min-obj [init-min] (let[last-min (atom init-min)] (defn do-min [x y] (reset! last-min (if (<= x y) x y))) (defn get-last [] (deref last-min)) {:get #(get-last) :min #(do-min %1 %2)})) A Min Object 11 http://thinkrelevance.com/blog/2009/08/12/rifle-oriented-programming-with-clojure-2.html
  • 12.
    A Min Object 12 (defnmin-obj [init-min] (let [last-min (atom init-min)] (defn do-min [x y] (reset! last-min (if (<= x y) x y))) (defn get-last [] (deref last-min)) {:get #(get-last) :min #(do-min %1 %2)})) (define min1 (min-obj 1000000))  Constructor
  • 13.
    A Min Object 13 (defnmin-obj [init-min] (let [last-min (atom init-min)] (defn do-min [x y] (reset! last-min (if (<= x y) x y))) (defn get-last [] (deref last-min)) {:get #(get-last) :min #(do-min %1 %2)})) (define min1 (min-obj 1000000)) ((min1 :min) 5 6)  Call to min()
  • 14.
    A Min Object 14 (defnmin-obj [init-min] (let [last-min (atom init-min)] (defn do-min [x y] (reset! last-min (if (<= x y) x y))) (defn get-last [] (deref last-min)) {:get #(get-last) :min #(do-min %1 %2)})) (define min1 (min-obj 1000000)) ((min1 :min) 5 6) ((min1 :get))  Fetch last min
  • 15.
    Agenda  Functional vsImperative languages  OOP in Functional languages (e.g., Clojure)  Data Encapsulation case studies  Simple mutability (persistence)  A simple object  Mutability support  Failings of the substitution model  The environment model  Method dispatch  Language comparisons 15
  • 16.
    (defn min-obj [init-min] (let[last-min (atom init-min)] (defn do-min [x y] (reset! last-min (if (<= x y) x y))) (defn get-last [] (deref last-min)) {:get #(get-last) :min #(do-min %1 %2)})) (define min1 (min-obj 1000000)) ((min1 :get)) The Problem: Binding last-min 16
  • 17.
    The Solution: Environments 17 Globalenvironment min: other variables parameters: x y body: (if …) (defn min [x y] (if (<= x y) x y))  What happens when you define min():
  • 18.
    The Solution: Environments 18 Globalenvironment min: other variables parameters: x y body: (if …) (defn min [x y] (if (<= x y) x y))  What happens when you define min():
  • 19.
    Simple Execution 19  Whathappens when you execute min(): Global environment min: other variables parameters: x y body: (if …) (min 5 6) E1 environment x: 5 y: 6 (if …)
  • 20.
    Simple Execution 20  Whathappens when you execute min(): Global environment min: other variables parameters: x y body: (if …) (min 5 6) E1 environment x: 5 y: 6 (if …) Variable references resolved by traversing environment chain
  • 21.
    (defn min-obj [init-min] (let[last-min (atom init-min)] (defn do-min [x y] (reset! last-min (if (<= x y) x y))) (defn get-last [] (deref last-min)) {:get #(get-last) :min #(do-min %1 %2)})) (define min1 (min-obj 1000000)) ((min1 :get)) How Does min-obj Get Defined? 21
  • 22.
    Object Definition 22 Global environment min-obj: othervariables parameters: init-min body: (let [... ) (defn min-obj [init-min] (let [...))  What happens when you define min-obj():
  • 23.
    Object Instantiation 23  Howdo you instantiate min-obj(): Global environment min-obj: other variables parameters: init-min body: (let [... ) (def min1 (min-obj 1000000)) min1: parameters: body: (:get #(…), :min #(…)) last-min: 1000000 do-min: get-last: Environment E1 parameters: x y body: (reset! …) parameters: body: (deref …)
  • 24.
    Object Instantiation 24  Howdo you instantiate min-obj(): Global environment min-obj: other variables parameters: init-min body: (let [... ) (def min1 (min-obj 1000000)) min1: parameters: body: (:get #(…), :min #(…)) last-min: 1000000 do-min: get-last: Environment E1 parameters: x y body: (reset! …) parameters: body: (deref …)
  • 25.
    Method Execution 25  Howdo you execute min(): Global environment min-obj: other variables parameters: init-min body: (let [...) ((min1 :min) 5 6) min1: parameters: body: (:get #(…), :min #(…)) last-min: 1000000 do-min: get-last: Environment E1 parameters: x y body: (reset! …) parameters: body: (deref ...) E2 x: 5 y: 6
  • 26.
    Functional Language OOP Data encapsulation as a result of  Constructor parameter accessible only within function  Binding of internal functions to constructor parameter allows state retention  Other points  Dismantling of environments amenable to access count tracking  Dispatcher can operate on any criteria, and is pre-wired for SOA-style message passing 26
  • 27.
    Future Investigation  Howto subclass  How inheritance works  Existing (or desirable) object frameworks  Why isn’t OOP very common in Clojure? 27
  • 28.
    Agenda  Functional vsImperative languages  OOP in Functional languages (e.g., Clojure)  Data Encapsulation case studies  Simple mutability (persistence)  A simple object  Mutability support  Failings of the substitution model  The environment model  Method dispatch  Language comparisons 28
  • 29.
    Selected Comparisons Deep Static Scope Data Encapsulation Clojure/LispArbitrary depth Yes Pascal Arbitrary depth Yes, but no instances Java/C++ No Yes 29
  • 30.
    Data Encapsulation Comparison (defnmin-obj [init-min] (let [last-min (atom init-min)] (defn do-min [x y] (reset! last-min (if (<= x y) x y))) (defn get-last [] (deref last-min)) {:get #(get-last) :min #(do-min %1 %2)})) (define min1 (min-obj 1000000)) ((min1 :min) 5 6) ((min1 :get)) 30 class min_obj { private int last_min; public min_obj(int init_min) { last_min = init_min;} public int min(int x, int y) { last_min = (x <= y ? x : y); return last_min; } public int get () { return last_min;} } min_obj a = new min_obj(1000000); a.min(5, 6); a.get(); Clojure Java
  • 31.
    Static Scoping inPascal program test; var a : integer; procedure outer(); var b : integer; procedure inner(); var c : integer; begin c := a + b; end; begin b := a; inner(); end; begin a := 0; outer(); end. 31 Evaluation Stack a prev-frame-ptr b prev-frame-ptr c prev-frame-ptr Compiler knows stack location of all variables in scope – no traversing
  • 32.
    Agenda  Functional vsImperative languages  OOP in Functional languages (e.g., Clojure)  Data Encapsulation case studies  Simple mutability (persistence)  A simple object  Mutability support  Failings of the substitution model  The environment model  Method dispatch  Language comparisons 32
  • 33.