Upgrade to Pro — share decks privately, control downloads, hide ads and more …

OOP is dead only if FP is dead

André Staltz
September 28, 2017

OOP is dead only if FP is dead

It is common to see Functional Programming (FP) presented as the opposite of Object-oriented Programming (OOP). These two programming paradigms have important differences, but they can share a lot in common, so they are not in direct opposition. In this talk, Andre will explore the gray area between OOP and FP, with code samples in JavaScript, TypeScript, and Haskell, kept easy enough enough for any programmer to follow.

André Staltz

September 28, 2017
Tweet

More Decks by André Staltz

Other Decks in Programming

Transcript

  1. Evaluate Execute Calculate the value of an expression Perform a

    sequence of get/set actions Imperative Functional
  2. Evaluate Execute (weight => height => weight / 
 (height

    * height * 0.01 * 0.01) )(70)(177) var weight = 70; var height = 177; var bmi = weight; bmi /= height; bmi /= height; bmi /= 0.01; bmi /= 0.01;
  3. Closures Objects Put data in an object, attach methods to

    the object Put data in a closure, functions refer to the closure
  4. Closures Objects const greeter = { isFemale: false, greet(name) {

    return this.isFemale ? "Hi Ms. " + name : "Hi Mr. " + name; } }; const greet = (isFemale => name => isFemale ? "Hi Ms. " + name : "Hi Mr. " + name )(false);
  5. Closures Objects const greeter = { // ... }; greeter.greet.bind({isFemale:

    true})('Lisa'); Advantage: allows changing the this object for a method.
  6. Closures Objects const greeter = { // ... }; greeter.greet.bind({isFemale:

    true})('Lisa'); Advantage: allows changing the this object for a method. Disadvantage: allows changing the this object for a method.
  7. Immutability Mutation Haskell import Data.IORef f :: Num a =>

    a -> IO a f x = do y <- newIORef 5 -- :: IORef Int writeIORef y 10 val <- readIORef y -- :: Int return 2 * val
  8. Immutability Mutation Haskell import Data.STRef import Control.Monad.ST f :: Num

    a => a -> a f x = runST $ do y <- newSTRef 5 -- :: STRef Int writeSTRef y 10 val <- readSTRef y -- :: Int return 2 * val
  9. Assignment
 syntax Assignment
 semantics Haskell do text <- readFile "foo"

    writeFile "bar" text readFile "foo" >>= writeFile "bar"
  10. Assignment
 syntax Assignment
 semantics Haskell do text <- readFile "foo"

    writeFile "bar" text readFile "foo" >>= writeFile "bar"
  11. Assignment
 syntax Assignment
 semantics strongConnect v graph index stack indices

    lowlinks output = do i <- readSTRef index modifySTRef' indices (I.insert v i) modifySTRef' lowlinks (I.insert v i) modifySTRef' index (+1) push stack v forM_ (graph A.! v) $ \w -> do wIndex <- I.lookup w <$> readSTRef indices if isNothing wIndex then do strongConnect w graph index stack indices lowlinks output vLowLink <- fromJust . I.lookup v <$> readSTRef lowlinks wLowLink <- fromJust . I.lookup w <$> readSTRef lowlinks modifySTRef' lowlinks (I.insert v $ min vLowLink wLowLink) else do wOnStack <- elem w <$> readSTRef stack when wOnStack $ do vLowLink <- fromJust . I.lookup v <$> readSTRef lowlinks modifySTRef' lowlinks (I.insert v $ min vLowLink (fromJust wIndex)) vLowLink <- fromJust . I.lookup v <$> readSTRef lowlinks vIndex <- fromJust . I.lookup v <$> readSTRef indices when (vLowLink == vIndex) $ do scc <- addSCC v [] stack modifySTRef' output (scc:) http://vaibhavsagar.com/blog/2017/05/29/imperative-haskell/
  12. Typed Dynamic Is x => 2 * x pure? const

    double = x => 2 * x; const lol = {}; lol.valueOf = Math.random; double(lol); // 0.21666564647375441 double(lol); // 1.4260443726695509
  13. Typed Dynamic Is x => 2 * x pure? const

    double: (x: number) => number = x => 2 * x;
  14. Typed Dynamic Abstraction = flexibility. integers = [1, 2..] list1

    = take 5 integers -- [1,2,3,4,5] list2 = take 10 integers -- [1,2,3,4,5,6,7,8,9,10] Haskell
  15. Typed Dynamic Inheritance In OOP: reusability of classes (= data

    + methods) In FP: reusability of type classes (= functions)
  16. Typed Dynamic Inheritance In OOP: reusability of classes (= data

    + methods) In FP: reusability of type classes (= functions)
  17. Typed Dynamic Inheritance In OOP: reusability of classes (= data

    + methods) In FP: reusability of type classes (= functions)
  18. Typed Dynamic Inheritance In OOP: reusability of classes (= data

    + methods) In FP: reusability of type classes (= functions)
  19. Typed Dynamic Inheritance In OOP: reusability of classes (= data

    + methods) In FP: reusability of type classes (= functions)
  20. Typed Dynamic Inheritance In OOP: reusability of classes (= data

    + methods) In FP: reusability of type classes (= functions)
  21. The real problem is that programmers have spent far too

    much time worrying about efficiency in the wrong places and at the wrong times; 
 premature optimization is the root of all evil (or at least most of it) in programming. – Donald Knuth
  22. Premature concretization is the root of all complexity (or at

    least most of it) in programming. – André Staltz
  23. Typed Dynamic JavaScript can unreliably do multiple inheritance. // Creating

    objects var o1, o2, o3, obj = multiInherit(o1={a:1}, o2={b:2}, o3={a:3, b:3}); // Setting properties obj.c = 3; // Reading properties obj.a; // 1 (inherited from o1) obj.b; // 2 (inherited from o2) obj.c; // 3 (own property) obj.d; // undefined (not found) https://stackoverflow.com/questions/9163341/multiple-inheritance-prototypes-in-javascript/31236132#31236132
  24. Typed Dynamic JavaScript can unreliably do multiple inheritance. function multiInherit

    (...protos) { return Object.create(new Proxy(Object.create(null), { get (target, prop, receiver) { var obj = protos.find(obj => prop in obj); return obj ? Reflect.get(obj, prop, receiver) : void 0; }, set (target, prop, value, receiver) { var obj = protos.find(obj => prop in obj); return Reflect.set(obj || Object.create(null), prop, value, receiver); }, has: (target, prop) => protos.some(obj => prop in obj), ownKeys(target) { // ... }, getOwnPropertyDescriptor(target, prop) { // ... }, *enumerate (target) { yield* this.ownKeys(target); }, preventExtensions: (target) => false, defineProperty: (target, prop, desc) => false, })); }
  25. Evaluate Execute Calculate the value of an expression Perform a

    sequence of get/set actions Imperative Functional