Life after OOP

Rasmus Buchmann & Maximilian Klein

Last Talks

Is it impossible to write great programs in X?

Everything is in the middle

If a language encourages a certain style, almost all of its programs will be in that style

Murphy's Corollary:

If that style is nasty, every program you have to fix or lib you need will be written in it

Functional Programming

Advantages

Understanding the Tar Pit

Example

      
std::string WhatDoIDo?(const std::vector<std::string> & dirs , char separator) {
  std::vector<std::string>::const_iterator vsi = dirs.begin();
  int mCC = vsi->length();
  std::string compareString = *vsi;
  for (vsi = dirs.begin() + 1; vsi != dirs.end(); vsi++) {
    std::pair<std::string::const_iterator , std::string::const_iterator> p =
      std::mismatch(compareString.begin(), compareString.end(), vsi->begin());
     if ((p.first - compareString.begin()) < mCC)
       mCC = p.first - compareString.begin();
  }
  std::string::size_type found = compareString.rfind(separator, mCC);
  return compareString.substr(0 , found);
}
  
Small, reusable parts

Pythonized example

    
#buggy and brittle, just for demonstration
def mismatch(a,b):
    smallest = min(len(a),len(b))
    for i in range(smallest):
        if a[i] != b[i]:
            return i
    return smallest

def whatDoIDo(dirs, separator):
    compareString = dirs[0]
    maxMatch = len(compareString)
    for currentDir in dirs[1:]:
        mLength = mismatch(currentDir, compareString)
        if mLength < maxMatch:
            maxMatch = mLength
    lastPathIndex = compareString[:maxMatch + 1].rfind(separator)
    return compareString[:lastPathIndex]
    
  

Declarative?

    
def whatDoIDo2(dirs, separator):
    maxMatching = mergeStringsWhileEqual(dirs)
    return substringUntilLast(separator, maxMatching)
    
  

More abstract

    
def whatDoIDo3(dirs, separator):
    maxMatching = merge(whileEqual, dirs)
    return substringUntilLast(separator,
                              toString(maxMatching))
    
  
Small, reusable parts

Functional Tools

    
#Combine lists, stop when "how" returns None
merge(how, lists)

#Take substring until last occurence of separator
substringUntilLast(separator, s)

#whileEqual(a,b,c,...,z) = a if all equal,  else None
whileEqual(*items)

#Members of list until first occurence of None
listUntilNone(l)
    
  
Small, reusable parts

Implementations

    
#demonstration code, more "pythonic" or plain better solutions possible

def merge(how, lists):
    return listUntilNone(map(how, *lists))

def substringUntilLast(separator, s):
    return s[:s.rfind(separator)+1]

def whileEqual(*items):
    return functools.reduce(lambda x,y : x if x == y else None, items)

def listUntilNone(l):
    return itertools.takeWhile(lambda x: x != None, l)

toString = ''.join
    
  
Small, reusable parts

Bonus

    
#define function without def and lambda for style points
whatDoIDo4 = compose(partial(substringUntilLast, "/"),
                     partial(merge, whileEqual))
    
  
Small, reusable parts

Summary

Imperative parent assistance
It's better to have 100 functions operating on 1 datastructure than 10 functions operating on 10 datastructures.
Alan Perlis
Small, reusable parts

Functional

Small, reusable parts?

OOP?

It's better to have 100 functions operating on 1 abstraction than 10 functions operating on 10 abstractions.
Alan Perlis, 2.0
Stronger Abstractions

Example - Elm


import Mouse

edgeLength = lift (uncurry max) Mouse.position

resizeableImage n = image n n "/Image.jpg"

main = lift resizeableImage edgeLength
 
Stronger Abstractions

Seq abstraction

Treating something as a sequence allows ALL sequence functions to be used on it

Stronger Abstractions

Streaming Example

    
(defn messages-from [client]
  (->> (:in @client)
       line-seq
       (map escape-control-chars)
       (remove str/blank?)
       (partition-by block-separator?)
       parse-block))
    
  
Stronger Abstractions

Lazyness

Stronger Abstractions

New directions

  
(def stats-graph
  {:n           (fnk [xs]   (count xs))
   :mean        (fnk [xs n] (/ (sum identity xs) n))
   :mean2       (fnk [xs n] (/ (sum #(* % %) xs) n))
   :variance    (fnk [mean mean2] (- mean2 (* mean mean)))})

(def stats (graph/eager-compile stats-graph))

(stats {:xs [1 2 3 6]})
  

Noteworthy

Referential Transparency

Idiocracy Avalanche

FP Foundations

Go Build!

Thank you for your attention!


Next presentation: 5 June, 16:15, here

Topic:The Actor Model!