I. the binary method problem A. what it is ------------------------------------------ BINARY METHODS def: a *binary method* is a method e.g., +, =, <, subset: ------------------------------------------ B. the problems ------------------------------------------ EXAMPLE class: Point superclass: Object instance variables: xValue yValue "instance methods" x: aNumber xValue := aNumber y: aNumber yValue := aNumber x ^xValue y ^yValue equal: p ^(xValue = p x) and: [yValue = p y] ------------------------------------------ Anything problematic about the equal method? ------------------------------------------ A USE OF THE POINT CLASS class: Procedure superclass: Object instance variables: "instance methods" breakit: p. | nuPt | nuPt := Point new x: 3.2. nuPt y: 4.5. ^p equal: nuPt ------------------------------------------ ------------------------------------------ THE SUBCLASS class: ColorPoint superclass: Point instance variables: cValue "instance methods" c: aString cValue := aString c ^cValue equal: p ^(cValue = p c) and: [super equal: p] ------------------------------------------ does that seem reasonable? 1. breaks subtyping ------------------------------------------ COLORPOINT IS NOT A SUBTYPE OF POINT | nuCPt | nuCPt := ColorPoint new. ((nuCpt x: 8.7) y: 9.1) c: 'red'. (Procedure new) breakit: nuCPt ------------------------------------------ what happens? How could this be patched? 2. need for privileged access ------------------------------------------ NEED FOR PRIVILEGED ACCESS class: IntSet superclass: Object instance variables: elts "instance methods" new elts := OrderedCollection new add: anInt elts addFirst: anInt includes: anInt elts includes: anInt superSetOf: anIntSet "???" ------------------------------------------ C. summary Is there just one "binary method" problem? II. multi-methods and Cecil-like languages A. semantics 1. models of objects ------------------------------------------ SEMANTIC MODELS OF OBJECTS objects as records (e.g. Smalltalk): !--------------------------! ! a Point object ! !--------------------------! | x ! *-----------> | y ! *-----------> !--------------------------! ! equal ! method(p2) ! ! print ! method() ! ! ... ! ... ! !--------------------------! objects with just data (CLOS, Dylan): !--------------------------! ! a Point object ! !--------------------------! | x ! *-----------> | y ! *-----------> !--------------------------! !-----------------------------------! ! equal generic function ! !-----------------------------------! ! Point x Point ! method(p1,p2) ! ! ClrPnt x ClrPnt ! method(cp1,cp2) ! !-----------------------------------! ------------------------------------------ ------------------------------------------ SEMANTIC MODELS OF OBJECTS (2) objects are just identities (BeCecil) !--------------------------! ! a Point object ! !--------------------------! !-----------------------------------! ! x generic function ! !-----------------------------------! ! Point ! storage(p) ! !-----------------------------------! !-----------------------------------! ! y generic function ! !-----------------------------------! ! Point ! storage(p) ! !-----------------------------------! !-----------------------------------! ! equal generic function ! !-----------------------------------! ! Point x Point ! method(p1,p2) ! ! ClrPnt x ClrPnt ! method(cp1,cp2) ! !-----------------------------------! ------------------------------------------ 2. storage tables ------------------------------------------ STORAGE TABLES example storage table for "x" !------------------------------! ! ! ! |----------------!-------------! | ! ! |----------------!-------------! ! ... ! ... ! |----------------!-------------! | (default) ! 0 ! !------------------------------! ------------------------------------------ Can we generalize this idea to multiple "arguments"? so how would you handle arrays? ------------------------------------------ VARIABLES AS STORAGE TABLES object i i inherits GenericFun_pro i has storage() := 3 produces |--------------------| | () | | |--------------------| | (default) | 3 | |--------------------| Use: ------------------------------------------ how would you desugar this? 3. multiple dispatch to generic functions ------------------------------------------ GENERIC FUNCTION CALL EXAMPLE def: a *generic function* is example: myPt() := mkPoint(3,4) myCP() := mkClrPnt(3,4,red) equal(myPt(), myPt()) equal(myPt(), myCP()) equal(myCP(), myPt()) equal(myCP(), myCP()) ------------------------------------------ What case gets run in each case? any errors? Does this solve (some of) the binary methods problem? ------------------------------------------ SEMANTICS OF GENERIC FUNCTION CALL (simplified multiple dispatch) def: a *case* is def: let the *specializers of a case* are def: a case c1 *overrides* c2 iff Meaning of call: f(e1, ..., en) 1. Evaluate e1,...,en to values v1,...vn 2. Let applicable(f,(v1,...,vn)) be the set of all cases in f such that 3. There must just 1 case in applicable(f,(v1,...,vn)) 4. Bind the actuals to the formals and invoke that case ------------------------------------------ what would the meaning of an assignment be? could we generalize the notion of a method to allow assignment? ------------------------------------------ SINGLE VS. MULTIPLE DISPATCH In *single dispatch* langauges the method found is based on In *multiple dispatch* languages the method found is based on ------------------------------------------ What languages are examples of each? B. the language BeCecil 1. Point example a. desugared code ------------------------------------------ POINT EXAMPLE (desugared and untyped version) object Point_pro Point_pro inherits any object x x inherits GenericFun_pro x has storage(p@Point_pro) := 0 object y y inherits GenericFun_pro y has storage(p@Point_pro) := 0 object equal equal inherits GenericFun_pro equal has method(p1@Point_pro, p2@Point_pro) { and(equal(x(p1),x(p2)), equal(y(p1),y(p2))) } ------------------------------------------ b. sugars ------------------------------------------ SYNTACTIC SUGARS SM "Make your language sweeter" Idea: find recurring patterns of syntax, ------------------------------------------ What examples do we have in the Point example? c. sugared version ------------------------------------------ POINT EXAMPLE (sugared version) object Point_pro inherits any field x of Point_pro := 0 field y of Point_pro := 0 gf equal equal has method(p1@Point_pro, p2@Point_pro) { and(equal(x(p1),x(p2)), equal(y(p1),y(p2))) } ------------------------------------------ Who benefits from this sugaring? 2. object creation ------------------------------------------ OBJECT CREATION -- static object myPoint inherits Point_pro ------------------------------------------ 3. color point example ------------------------------------------ COLOR POINT object ClrPnt_pro inherits Point_pro field c of ClrPntPro := clear ------------------------------------------ 4. objects/types, inheritance/subtyping 5. information hiding have we lost anything in going to this kind of language? ------------------------------------------ HIDE DECLARATION object Grayscape_pro inherits any hide -- private delarations in -- public declarations initialize has method(c@Grayscale_pro, inten@float_pro) { := truncate(multiply( min(max(0.0, inten) 1.0), 255.0)); c } intensity has method(c@Grayscape_pro){ divide(mkFloat( , 255.0)) } paint has method(c@Grayscale_pro, r@region_pro) {...} end intensity has acceptor(c@Grayscale_pro) := f { initialize(c, f) } ------------------------------------------ does this maintain the invariant in spite of clients? 6. current research ------------------------------------------ SEPARATE DEVELOPMENT AND MERGE Point / \ ClrPnt ThreeDPnt Want to: ------------------------------------------ ------------------------------------------ WHAT COULD GO WRONG? Coverage for equal 1st \ 2nd | Point | ClrPnt | ThreeDPnt ========================================= Point | | | ClrPnt | | | ThreeDPnt | | | ------------------------------------------ Does this problem occur in single dispatch languages? Why? What could we do about it?