DOC PREVIEW
UW CSE 341 - Lecture Notes

This preview shows page 1 out of 3 pages.

Save
View full document
View full document
Premium Document
Do you want full access? Go Premium and unlock all 3 pages.
Access to all documents
Download any document
Ad free experience
Premium Document
Do you want full access? Go Premium and unlock all 3 pages.
Access to all documents
Download any document
Ad free experience

Unformatted text preview:

CSE341: Programming Languages Lecture 23 OO vs. Functional Decomposition; Adding Operations & Variants; Double-Dispatch Dan Grossman Fall 2011 Breaking things down • In functional (and procedural) programming, break programs down into functions that perform some operation • In object-oriented programming, break programs down into classes that give behavior to some kind of data This lecture: – These two forms of decomposition are so exactly opposite that they are two ways of looking at the same “matrix” – Which form is “better” is somewhat personal taste, but also depends on how you expect to change/extend software – For some operations over two (multiple) arguments, functions and pattern-matching are straightforward, but with OOP we can do it with double dispatch (multiple dispatch) Fall 2011 2 CSE341: Programming Languages The expression example Well-known and compelling example of a common pattern: – Expressions for a small language – Different variants of expressions: ints, additions, negations, … – Different operations to perform: eval, toString, hasZero, … Leads to a matrix (2D-grid) of variants and operations – Implementation will involve deciding what “should happen” for each entry in the grid regardless of the PL Fall 2011 3 CSE341: Programming Languages eval toString hasZero … Int Add Negate … Standard approach in ML • Define a datatype, with one constructor for each variant – (No need to indicate datatypes if dynamically typed) • Define a function for each operation • So “fill out the grid” via one function per column with one case-expression branch for each grid position – Can use a wildcard pattern if there is a default for multiple entries in a column See lec23_stage1.sml Fall 2011 4 CSE341: Programming Languages eval toString hasZero … Int Add Negate … Standard approach in OOP • Define a class, with one abstract method for each operation – (No need to indicate abstract methods if dynamically typed) • Define a subclass for each variant • So “fill out the grid” via one class per row with one method implementation for each grid position – Can use a method in the superclass if there is a default for multiple entries in a column See lec23_stage1.rb and lec23_stage1.java Fall 2011 5 CSE341: Programming Languages eval toString hasZero … Int Add Negate … A big CSE341 punchline • FP and OOP often doing the same thing in exact opposite way – Organize the program “by rows” or “by columns” • Which is “most natural” may depend on what you are doing (e.g., an interpreter vs. a GUI) or personal taste • Code layout is important, but there’s no perfect way since software has many dimensions of structure – Tools, IDEs can help with multiple “views” (e.g., rows / columns) Fall 2011 6 CSE341: Programming Languages eval toString hasZero … Int Add Negate …Now for stage 2: FP • For implementing our grid so far, SML / Racket style usually by column and Ruby / Java style usually by row • But beyond just style, this decision affects what (unexpected?) software extensions are easy and/or do not change old code • Functions: – Easy to add a new operation, e.g., noNegConstants – Adding a new variant, e.g., Mult requires modifying old functions, but ML type-checker gives a to-do list if we avoided wildcard patterns in Stage 1 Fall 2011 7 CSE341: Programming Languages eval toString hasZero noNegConstants Int Add Negate Mult Now for stage 2: OOP • For implementing our grid so far, SML / Racket style usually by column and Ruby / Java style usually by row • But beyond just style, this decision affects what (unexpected?) software extensions are easy and/or do not change old code • Objects: – Easy to add a new variant, e.g., Mult – Adding a new operation, e.g., noNegConstants requires modifying old classes, but Java type-checker gives a to-do list if we avoided default methods in Stage 1 Fall 2011 8 CSE341: Programming Languages eval toString hasZero noNegConstants Int Add Negate Mult The other way is possible • Functions allow new operations and objects allow new variants without modifying existing code even if they didn’t plan for it – The programming style “just works that way” • Functions can support new variants somewhat awkwardly “if they plan ahead” – See datatype 'a ext_exp and eval_ext at bottom of lec23.sml if interested • Objects can support new operations somewhat awkwardly “if they plan ahead” – The popular Visitor Pattern (not shown here), which uses the double-dispatch pattern (used next for another purpose) Fall 2011 9 CSE341: Programming Languages Thoughts on Extensibility • Making software extensible is valuable and hard – If you know you want new operations, use FP – If you know you want new variants, use OOP – If both? Languages like Scala try; it’s a hard problem – Reality: The future is often hard to predict! • Extensibility is a double-edged sword – Code more reusable without being changed later – But makes original code more difficult to reason about locally or change later (could break extensions) – Often language mechanisms to make code less extensible (ML modules hide datatypes; Java’s final prevents subclassing/overriding) Fall 2011 10 CSE341: Programming Languages Stage 3: Binary operations • Situation is more complicated if an operation is defined over multiple arguments that can have different variants – Can arise in original program or after an extension • Our example: – Include variants String and Rational – (Re)define Add to work on any pair of Int, String, Rational in either order • String-concatenation if >= 1 arg is a String, else math – (Just to keep example smaller, Negate and Mult still work only on Int, with a run-time error for a String or Rational) Fall 2011 11 CSE341: Programming Languages Binary operation in SML Add works differently for most combinations of Int, String, Rational – Run-time error for any other kinds of expression Natural approach: pattern-match on the pair of values – For commutative possibilities, can re-call with (v2,v1) Fall 2011 12 CSE341: Programming Languages fun add_values (v1,v2) = case (v1,v2) of (Int i, Int j) => Int (i+j) | (Int i, String s) => String (Int.toString i ^ s) | (Int i, Rational(j,k)) => Rational (i*k+j,k) | (Rational _, Int _) => add_values (v2,v1) | … (* 5 more cases


View Full Document

UW CSE 341 - Lecture Notes

Documents in this Course
Macros

Macros

6 pages

Macros

Macros

6 pages

Macros

Macros

3 pages

Mutation

Mutation

10 pages

Macros

Macros

17 pages

Racket

Racket

25 pages

Scheme

Scheme

9 pages

Macros

Macros

6 pages

Load more
Download Lecture Notes
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Lecture Notes and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Lecture Notes 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?