http://www.higherorderlogic.com/refactoring-to-functional.zip

Refactoring to
functional

Steve Freeman @sf105

Julian Kelsey @scrawlings, Andy Parker @aparker42

Requires access to a laptop with Java 1.6+ and a refactoring IDE

Today

Functional programming?

val a = doubled(b)
  
val doubledCounts = eachDoubled(counts)

First class functions

val plusOne = lambda x: x + 1
  
val incremented = applied(count, plusOne)
def applied(value, oneArgFunction):
  return oneArgFunction(value)

Lots of collections

val backwards = reversed(forwards)
  
val incremented = map(counts, plusOne)
val shouty = map(inputStream, inUpperCase)
incremented = [x + 1 for x in counts]

Collection manipulation

val plusThenMinus = concat(
  filter(values, isPositive),
  filter(values, isNegative))

val total = reduce(values, 0, add)
val idToAccount =
  uniqueIndex(accounts, account => account.id)
  

Why functional?

val allPostiveRecordsAreValid =
  all(filter(records, isPositive), isValid)
  records select (r => r.value > 0)
          all (r => r.isValid)
  all([r.isValid for r in records
                       if r.value > 0])

What will be different?

daily = values.getConvertedToDaily()
daily = values asDailyResults
def sum(values):
  return reduce(values, 0, adder)

In the real world

In the real world (Java)

Quick intro to Guava

Function<I,O>

Function<Integer, String> asString
  = new Function<Integer, String>() {
      public String apply(Integer input) {
        return String.valueOf(input);
      }
    };
assertEquals("123", asString.apply(123));

Predicate<T>

Predicate<String> isBlank 
  = new Predicate<String>() {
      public boolean apply(String input) {
        return input.matches("\\s*");
      }
    };

assertFalse(isBlank.apply("Some Input")); 
assertTrue(isBlank.apply("  "));

transform()

Iterable<O> transform(Iterable<I>, Function<I, O>)
Iterable<Integer> numbers = asList(1, 2, 3);

Iterable<String> strings =
    Iterables.transform(numbers, asString);
  
assertThat(strings, contains("1", "2", "3"));

filter()

Iterable<T> filter(Iterable<T>, Predicate<T>)
List<Integer> strings =
    asList("a", " ", "c", "  ");

Iterable<String> blanks = 
    Iterables.filter(strings, isBlank);
  
assertThat(blanks, contains(" ", "  "));

Boolean queries

boolean all(Iterable<T>, Predicate<T>)
boolean any(Iterable<T>, Predicate<T>)
assertTrue(
  Iterables.all(asList(" ", "  "), isBlank));
assertFalse(all(asList("s", " "), isBlank));

assertTrue(
  Iterables.any(asList("a", " "), isBlank));
assertFalse(any(asList("a", "b"), isBlank));
    

reduce()

R reduce(Iterable<I>, R, Function<I, R>)
assertThat(
    reduce(asList(1, 2, 3), 0, addition),
    equalTo(6));
assertThat(
    reduce(asList(1, 2, 3), 10, subtraction),
    equalTo(4));