1 Structure and Interpretation of Computer Programs Modularity, Objects, and State (part 1) Abelson & Sussman 2 UC San Diego CSE 294 May 11, 2011 Barry Demchak
Agenda Functional vs Imperative languages 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) functional programming 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 imperative programming 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) 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 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 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! ) (swap! )
(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
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 )) 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 )) ((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 )) ((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 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 )) ((min1 :get)) The Problem: Binding last-min 16
The Solution: Environments 17 What happens when you define min():
The Solution: Environments 18 What happens when you define min():
Simple Execution 19 What happens when you execute min():
Simple Execution 20 What happens when you execute min(): 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 )) ((min1 :get)) How Does min-obj Get Defined? 21
Object Definition 22 What happens when you define min-obj():
Object Instantiation 23 How do you instantiate min-obj():
Object Instantiation 24 How do you instantiate min-obj():
Method Execution 25 How do you execute min():
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 Language comparisons 28
Selected Comparisons Deep Static Scope Data Encapsulation Clojure/LispArbitrary depthYes PascalArbitrary depthYes, but no instances Java/C++NoYes 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 )) ((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( ); 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 c no traversing 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