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()
RtfIterables
(not in Guava)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));