<<

Object Oriented Programming (OOP) IIIA

o New o Actions Æ Objects o Objects Å Actions

o Object-oriented = Objects + Classes + Inheritance

TAPIA 2005-2006

Imperative programming IIIA

o OOP (Object-Oriented Programming) related o Local state, delegation, inheritance o History (Norvig,465): Algol 60 Æ SIMULA o Lisp extensions: o (69) o Flavors (79) o New Flavors (81) o Common Loops (88) o CLOS (91): standard

TAPIA 2005-2006 History IIIA Dahl 1966 Algol60 Simula Classes single inheritance Nygaard LISP world Kay 1969 Smalltalk Goldberg Ingalls Steele 1976 LAMBDA Cannon 1979 Flavors method combination Weinreb Symbolics 1981 New Flavors generic functions

Xerox 1982 CommonLoops multimethods AT& 1986 C++ Bell labs Meyer 1988 Oaklisp Eiffel Lang 1988 Perlmutter CLOS Steele 1991 JAVA

TAPIA 2005-2006

AOP vs. OOP (Shoham) IIIA

OOP AOP Basic unit Object (passive) Agent (active)

State without restriction belief, commitment, competence, preferences, …

Computation Message passing, methods Message passing, methods

Type of messages without restriction Inform, request, offer, promise, reject, …

Message no Honesty, consistency, rationality, restrictions …

TAPIA 2005-2006 Nomenclature IIIA

o Object: encapsulated local state and behavior o Class: describes similar objects with the same behavior and structure. o Instance: object belonging to a class. o Class Variable: variable shared by all the members of a class. o Instance Variable: encapsulated variable of an object. o : its behavior depends on the types or classes of the arguments.

TAPIA 2005-2006

Nomenclature IIIA

o Message: Action name. Equivalent to a generic function. o Method: Specialization of a generic function. o Delegation: an object passes a task to another object. o Multimethod: method with more than one argument o Inheritance: to define new classes that are a specialization of a more general one. o Multiple inheritance: from more than one father class.

TAPIA 2005-2006 Object-Oriented Style IIIA

o Example: Bank account class o Local state and functions o Instance variables: balance, interest rate o Messages and methods: withdraw, deposit, balance, name, interest o It is not possible to manipulate the variables in a closure using CommonLisp. o INSPECT is implementation dependent

TAPIA 2005-2006

Object-Oriented Style IIIA

(defun new-account (name &optional (balance 0.00) (interest-rate .06)) “new account with the following messages:" #'(lambda (message) (case message (withdraw #'(lambda (amt) (if (<= amt balance) (decf balance amt) 'insufficient-funds))) (deposit #'(lambda (amt) (incf balance amt))) (balance #'(lambda () balance)) (name #'(lambda () name)) (interest #'(lambda () (incf balance (* interest-rate balance)))))))

TAPIA 2005-2006 SEND IIIA

o Send function (Flavors) implements the control of objects.

(defun get-method (object message) “Returns the method for the given message" (funcall object message))

(defun send (object message &rest args) “Applies the method for the message with the arguments” (apply (get-method object message) args))

TAPIA 2005-2006

SEND IIIA o Execution examples

> (setf acct (new-account "J. Random Customer" 1000.00)) #

> (send acct 'withdraw 500.00) Æ 500.0

> (send acct 'deposit 123.45) Æ 623.45

> (send acct 'name) Æ "J. Random Customer"

> (send acct 'balance) Æ 623.45

TAPIA 2005-2006 Generic functions IIIA

o The syntax of send is not useful. We are interested in expressions of the following type: o (mapcar 'balance accounts) o Using messages: o (mapcar #'(lambda (acct) (send acct 'balance)) accounts) o Generic functions will find the correct method of an object, specialized on a message type. o (defun withdraw (object &rest args) “withdraw is a generic function over objects." (apply (get-method object 'withdraw) args)) o We can write: o (withdraw acct x) o Instead of: o (send acct 'withdraw x)

TAPIA 2005-2006

Classes IIIA

o Using Macros o Easier read and write object-oriented code o Create a new class o Methods o Generic functions for each message o Class variables o Instance variables

TAPIA 2005-2006 Classes IIIA

(define-class account (name &optional (balance 0)) ((interest-rate .06)) (withdraw (amt) (if (<= amt balance (decf balance amt) 'insufficient-funds)) (deposit (amt) (incf balance amt)) (balance () balance) (name () name) (interest () (incf balance (* interest-rate balance))))

TAPIA 2005-2006

Classes IIIA

(defmacro define-class (class inst-vars class-vars &body methods) “class definition." `(let ,class-vars (mapcar #'ensure-generic-fn ' ,(mapcar #'first methods)) (defun ,class ,inst-vars #'(lambda (message) (case message ,@(mapcar #'make-clause methods))))))

(defun make-clause (clause) "Translate a message from define-class into a case clause." `(,(first clause) #'(lambda ,(second clause) ,@(rest (rest clause)))))

TAPIA 2005-2006 Classes II IIIA

(defun ensure-generic-fn (message) “defines a generic function." (unless (or (generic-fn-p message) (eq message ‘otherwise)) (let ((fn #'(lambda (object &rest args) (apply (get-method object message) args)))) (setf (symbol-function message) fn) (setf (get message 'generic-fn) fn))))

(defun generic-fn-p (fn-name) “is fn-name a function?" (and (fboundp fn-name) (eq (get fn-name 'generic-fn) (symbol-function fn-name))))

TAPIA 2005-2006

Classes II IIIA

(define-class account (name &optional (balance 0)) ((interest-rate .06)) (withdraw (amt) (if (<= amt balance (decf balance amt) 'insufficient-funds)) (deposit (amt) (incf balance amt)) (balance () balance) (name () name) (interest () (incf balance (* interest-rate balance))))

TAPIA 2005-2006 Classes III IIIA o Macro expansion:

(LET ((INTEREST-RATE 0.06)) (MAPCAR #'ENSURE-GENERIC-FN '(WITHDRAW DEPOSIT BALANCE NAME INTEREST)) (DEFUN ACCOUNT (NAME &OPTIONAL (BALANCE 0.0)) #'(LAMBDA (MESSAGE) (CASE MESSAGE (WITHDRAW #'(LAMBDA (AMT) (IF (<= AMT BALANCE) (DECF BALANCE AMT) 'INSUFFICIENT-FUNDS))) (DEPOSIT #'(LAMBDA (AMT) (INCF BALANCE AMT))) (BALANCE #'(LAMBDA NIL BALANCE)) (NAME #'(LAMBDA NIL NAME)) (INTEREST #'(LAMBDA NIL (INCF BALANCE (* INTEREST-RATE BALANCE))))))))

TAPIA 2005-2006

Classes III IIIA

o Using the new objects: o > (setf acct2 (account "A. User" 2000.00)) # o > (deposit acct2 42.00) -> 2042.0 o > (interest acct2) -> 2164.52 o > (balance acct2) -> 2164.52 Previous !!! o > (balance acct) -> 623.45 object

TAPIA 2005-2006 Delegation I IIIA

o Account with password:

(define-class password-account (password acct) () (change-password (pass new-pass) (if (equal pass password) (setf password new-pass) 'wrong-password)) (otherwise (pass &rest args) (if (equal pass password) (apply message acct args) 'wrong-password)))

TAPIA 2005-2006

Delegation I IIIA

o Details of the define-class macro: message and otherwise.

> (setf acct3 (password-account "secret" acct2)) # > (balance acct3 "secret") -> 2164.52 > (withdraw acct3 "guess" 2000.00) -> WRONG-PASSWORD > (withdraw acct3 "secret" 2000.00) -> 164.52

TAPIA 2005-2006 Delegation II IIIA

o The same technique for “limited” accounts:

(define-class limited-account (limit acct) () (withdraw (amt) (if (> amt limit) 'over-limit (withdraw acct amt))) (otherwise (&rest args) (apply message acct args)))

TAPIA 2005-2006

Delegation II IIIA

o > (setf acct4 (password-account "pass" (limited-account 100.00 (account "A. Thrifty Spender" 500.00)))) # o > (withdraw acct4 "pass" 200.00) Æ OVER-LIMIT o > (withdraw acct4 "pass" 20.00) Æ 480.0 o > (withdraw acct4 "guess" 20.00) WRONG-PASSWORD

TAPIA 2005-2006 Delegation III IIIA o Each class implements a different withdraw method. Sending the message withdraw to the object acct4 : 1. password-account method validates the password. 2. If correct, sends the message withdraw to the limited-account object. 3. If under the limit, sends the message withdraw to the account object. o Notice the differences with the procedural version (defun withdraw (acct amt &optional pass) (cond ((and (typep acct 'password-account) (not (equal pass (account-password acct)))) 'wrong-password) ((and (typep acct 'limited-account) (> amt (account-limit account))) 'over-limit) ((> amt balance) 'insufficient-funds) (t (decf balance amt))))

TAPIA 2005-2006

Inheritance I IIIA o Classes are hierarchically organized. It is necessary to make explicit this hierarchy. o Lisp structures implement inheritance: (defstruct (limited-account (:include account)) limit)

o The same for classes:

(define-class limited-account account (limit) () (withdraw (amt) (if (>amt limit) 'over-limit (call-next-method)))

TAPIA 2005-2006 Inheritance II IIIA

o Multiple inheritance :

(define-class limited-account-with-password (password-account limited-account))

o Union of the functionalities belonging to the two classes. o No new variable or methods.

TAPIA 2005-2006

History IIIA Dahl 1966 Algol60 Simula Classes single inheritance Nygaard LISP world Kay 1969 Smalltalk Goldberg Ingalls Steele 1976 LAMBDA Cannon 1979 Flavors multiple inheritance method combination Weinreb Symbolics 1981 New Flavors generic functionsCommon Lisp Object System Xerox 1982 CommonLoops multimethods AT&T 1986 C++ Bell labs Meyer 1988 Oaklisp Eiffel Lang 1988 Perlmutter CLOS Steele 1991 JAVA

TAPIA 2005-2006 CLOS: defclass IIIA Our System CLOS define-class defclass methods in class defmethod class-name make-instance call-next-method call-next-method ensure-generic-fn ensure-generic-function

o Definition of: o Classes: defclass o Methods: delmethod o Instances: make-instance. o Syntax of class definition: (defclass class-name (superclass...) (slot-specifier...) optional-class-option...)

TAPIA 2005-2006

defclass (slots and implicit methods) IIIA

(defclass account () ((name :initarg :name :reader name) (balance :initarg :balance :initform 0.00 :accessor balance) (interest-rate :allocation :class :initform .06 :reader interest-rate)))

> (setf a1 (make-instance 'account :balance 5000.00 :name "Fred")) # > (name a1) Æ "Fred" > (balance a1) Æ 5000.0 > (interest-rate a1) Æ 0.06

TAPIA 2005-2006 CLOS: defmethod IIIA

(defmethod method-name (parameter...) body...)

(defmethod withdraw ((acct account) amt) (if (< amt (balance acct)) (decf (balance acct) amt) 'insufficient-funds))

o limited-account class is a subclass of account class.

(defclass limited-account (account) ((limit :initarg :limit :reader limit)))

(defmethod withdraw ((acct limited-account) amt) (if (> amt (limit acct)) 'over-limit (call-next-method))) TAPIA 2005-2006

Inheritance example IIIA > (setf a2 (make-instance 'limited-account :name "A. Thrifty Spender" :balance 500.00 :limit 100.00)) #

Values to slots inherited from the account class.

> (name a2) Æ "A. Thrifty Spender"

Name method is inherited.

> (withdraw a2 200.00) Æ OVER-LIMIT > (withdraw a2 20.00) Æ 480.0 Multiple: left to right Using call-next-method.

TAPIA 2005-2006 Examples IIIA (defclass audited-account (account) ((audit-trail :initform nil :accessor audit-trail)))

(defmethod withdraw :before ((acct audited-account) amt) (push (print `(withdrawing ,amt)) (audit-trail acct)))

(defmethod withdraw :after ((acct audited-account) amt) RETURN (push (print `(withdrawal (,amt) done)) (audit-trail acct)))

o Order: 1. All the methods :before, from more specific to more general 2. Primary methods: the most specific (call-next-method) 3. All the methods :after, from more general to more specific o Auxiliary method :around o The most specific (call-next-method)

TAPIA 2005-2006

Examples IIIA

> (setf a3 (make-instance 'audited-account :balance 1000.00)) #

> (withdraw a3 100.00) (WITHDRAWING 100.0) (WITHDRAWAL (100.0) DONE) 900.0

> (audit-trail a3) ((WITHDRAWAL (100.0) DONE) (WITHDRAWING 100.0))

> (setf (audit-trail a3) nil) NIL o CLOS problem: Encapsulation of methods. Methods are not defined into the classes.

TAPIA 2005-2006 OOP Example: Search tools IIIA

o OOP is useful to implement two important models of representation: 1. Isomorphism between real objects and computational objects. 2. Program combination as a building tool for programming.

o The second model is useful for searching. o Classification of search problems: o Domain: planning, games, etc. o Topology: tree, graph, etc. o Search strategy: depth-first, breadth-first, etc.

o Modularity

TAPIA 2005-2006

Search tools IIIA

o A problem contains a space of states.

(defclass problem () ((states :initarg :states :accessor problem-states)))

TAPIA 2005-2006 Search I IIIA

o The definition of the search method of the problem class uses generic functions.

(defmethod searcher ((prob problem)) “Finding a solution state" (cond ((no-states-p prob) ‘fail) ((goal-p prob) (current-state prob)) (t (let ((current (pop-state prob))) (setf (problem-states prob) (problem-combiner prob (problem-successors prob current) new (problem-states prob)))) old (searcher prob))))

TAPIA 2005-2006

Search I IIIA

(defmethod current-state ((prob problem)) "The current state is the first of the possible states." (first (problem-states prob)))

(defmethod pop-state ((prob problem)) "Remove and return the current state." (pop (problem-states prob)))

TAPIA 2005-2006 Search II IIIA

(defmethod no-states-p ((prob problem)) "Are there any more unexplored states?" (null (problem-states prob)))

(defmethod searcher :before ((prob problem)) (format t "~&;; Search: ~a" (problem-states prob)))

(defmethod searcher ((prob problem)) “Finding a solution state" (cond ((no-states-p prob) ‘fail) ((goal-p prob) (current-state prob)) (t (let ((current (pop-state prob))) (setf (problem-states prob) (problem-combiner prob (problem-successors prob current) (problem-states prob)))) (searcher prob)))) TAPIA 2005-2006

Search II IIIA

Problem subclass: problems with a goal.

(defclass eql-problem (problem) ((goal :initarg :goal :reader problem-goal)))

(defmethod goal-p ((prob eql-problem)) (eql (current-state prob) (problem-goal prob)) (defmethod searcher ((prob problem)) “Finding a solution state" (cond ((no-states-p prob) ‘fail) ((goal-p prob) (current-state prob)) (t (let ((current (pop-state prob))) (setf (problem-states prob) (problem-combiner prob (problem-successors prob current) (problem-states prob)))) (searcher prob)))) TAPIA 2005-2006 Strategies IIIA

o Two subclasses of problems with search strategies:

(defclass dfs-problem (problem)() (:documentation "Depth-first search problem."))

(defclass bfs-problem (problem)() (:documentation "Breadth-first search problem."))

(defmethod problem-combiner ((prob dfs-problem) new old) "Depth-first search looks at new states first." (append new old))

(defmethod problem-combiner ((prob bfs-problem) new old) "Breadth-first search looks at old states first." (append old new))

TAPIA 2005-2006

Domain and combination IIIA

o Subclass of problem representing the topology type and the domain knowledge by means of successors computing. (defclass binary-tree-problem (problem) ())

(defmethod problem-successors ((prob binary-tree-problem) state) (let ((n (* 2 state))) (list n (+ n 1))))

o Finally we show the power of multiple inheritance by combining: topology, strategy and the problem type (goal-oriented).

(defclass binary-tree-eql-bfs-problem (binary-tree-problem eql-problem bfs-problem) ())

TAPIA 2005-2006 Run the example IIIA > (setf p1 (make-instance 'binary-tree-eql-bfs-problem :states '(1) :goal 12)) # > (searcher p1) ;; Search: (1) ;; Search: (2 3) ;; Search: (3 4 5) ;; Search: (4 5 6 7) ;; Search: (5 6 7 8 9) ;; Search: (6 7 8 9 10 11) ;; Search: (7 8 9 10 11 12 13) ;; Search: (8 9 10 11 12 13 14 15) ;; Search: (9 10 11 12 13 14 15 16 17) ;; Search: (10 11 12 13 14 15 16 17 18 19) ;; Search: (11 12 13 14 15 16 17 18 19 20 21) ;; Search: (12 13 14 15 16 17 18 19 20 21 22 23) 12 TAPIA 2005-2006

First summary IIIA

Problem states, Current state, pop-state no-states-p, searcher bfs-problem problem-combiner eql-problem Goal goal-p binary-tree-problem dfs-problem problem-successors problem-combiner

binary-tree-eql-bfs-problem

TAPIA 2005-2006 Other search strategies IIIA o Advantages of modularity

(defclass best-problem (problem) () (:documentation "A Best-first search problem."))

(defmethod problem-combiner ((prob best-problem) new old) "Best-first search sorts new and old according to cost-fn." (sort (append new old) #'< :key #'(lambda (state) (cost-fn prob state))))

(defmethod cost-fn ((prob eql-problem) state) (abs (- state (problem-goal prob))))

( (defclass beam-problem (problem) ((beam-width :initarg :beam-width :initform nil :reader problem-beam-width)))

(defmethod problem-combiner :around ((prob beam-problem) new old) (subseq (call-next-method) 0 (problem-beam-width prob))) TAPIA 2005-2006

New combination IIIA (defclass binary-tree-eql-best-beam-problem (binary-tree-problem eql-problem best-problem beam-problem) ())

> (setf p3 (make-instance 'binary-tree-eql-best-beam-problem :states '(1) :goal 12 :beam-width 3)) #

> (searcher p3) ;; Search: (1) ;; Search: (3 2) ;; Search: (7 6 2) ;; Search: (14 15 6) ;; Search: (15 6 28) ;; Search: (6 28 30) ;; Search: (12 13 28) 12 TAPIA 2005-2006 New schema IIIA

Problem states, Current state, pop-state no-states-p, searcher best-problem problem-combiner eql-problem Goal goal-p cost-fn binary-tree-problem beam-problem problem-successors problem-combiner

binary-tree-eql-best-beam-problem

TAPIA 2005-2006