lambda expressions: myths and mistakes - richard warburton (jclarity)

70
Lambdas: Myths and Mistakes by Richard Warburton

Upload: jaxlondonconference

Post on 12-May-2015

1.446 views

Category:

Technology


1 download

DESCRIPTION

Presented at JAX London 2013 tl;dr - How will the everyday developer cope with Java 8’s Language changes? Java 8 will ship with a powerful new abstraction - Lambda Expressions (aka Closures) and a completely retooled set of Collections libraries. In addition interfaces have changed through the addition of default and static methods. The ongoing debate as to whether Java should include such language changes has resulted in many vocal opinions being espoused. Sadly few of these opinions have been backed up by practical experimentation and experience. - Are these opinions just myths?

TRANSCRIPT

Page 1: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Lambdas:Myths andMistakesby Richard Warburton

Page 2: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

the critical design tool for softwaredevelopment is a mind well educated indesign principles. It is not ... technology.

Craig Larman

Page 3: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Who am I?Currently work at jClarity

Focus on Performance Tuning

Adopt a JSR (Date and Time + Lambdas)

Impending O'Reilly book on Lambda

Expressions in Java 8.

Page 4: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Talk StructureWhy am I talking about this?

Intro to Lambda Expressions

Beyond the Myths

Functional Thinking

Page 5: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Why am Italking about

this?

Page 6: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Lambda Expressions arecoming in Java 8!

Page 7: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

lots of discussion/debate

Page 8: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

How can we help?Adopt-a-JSR

Page 9: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Adopt-a-JSR?More community driven standards

Hackdays

Serve on Expert Groups

Page 10: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Some discussionunimportant

Concrete Examples focus discussion

Page 11: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Intro toLambda

Expressions

Page 12: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Overview of LambdasGoal: Better Libraries

Example: Collections with Data

Parallelism

Approach: Allow Code as Data

Page 13: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Action Listenerbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { System.out.println("button clicked"); }});

Page 14: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Code as Databutton.addActionListener( ?);

Page 15: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Need a parameterbutton.addActionListener(event

);

Page 16: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Lambda Examplebutton.addActionListener(event -> System.out.println("button clicked"));

Page 17: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

No parametersRunnable helloWorld = () -> System.out.println("Hello World");

Page 18: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Variable CaptureString name = getUserName();button.addActionListener(event -> System.out.println("hi " + name));

Page 19: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Functional InterfacesEverything in Java has a type

Problem: Need types to represent

Functions

Solution: Use interfaces

Page 20: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Functional Interfacespublic interface ActionListener extends EventListener { public void actionPerformed(ActionEvent event);}

Page 21: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

StreamsSupport automated data parallelism

Build computation pipelines

Iterator with inversion of control

Page 22: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

External Iterationint count = 0;for (Artist artist : artists) { if (artist.isFrom("London")) { count++; }}

Page 23: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Internal Iterationartists.stream() .filter(artist -> artist.isFrom("London")) .count();

Page 24: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

map

Page 25: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

mapList<String> collected = Stream.of("a", "b", "hello") .map(string -> string.toUpperCase()) .collect(toList());

assertEquals(asList("A", "B", "HELLO"), collected);

Page 26: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

reduce

Page 27: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

reduceint sum = Stream.of(1, 2, 3, 4) .reduce(0, (acc, x) -> acc + x);

assertEquals(10, sum);

Page 28: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

filter

Page 29: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

filterList<String> beginningWithNumbers = Stream.of("a", "1abc", "abc1") .filter(value -> isDigit(value.charAt(0))) .collect(toList());

assertEquals(asList("1abc"), beginningWithNumbers);

Page 30: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Putting it all togetherfor a given an album, find the nationality of every band

playing on that album

Page 31: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Putting it all together (2)1. transform an album into its artists2. figure out which artists are bands3. find the nationalities of each band

Page 32: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Putting it all together (3)List<String> origins = album.getMusicians() .filter(artist -> artist.getName().startsWith("The")) .map(artist -> artist.getNationality()) .collect(toList());

Page 33: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Method Referencesstr -> str.lengthString::length

x -> foo.bar(x)foo::bar

str -> new Name(str)Name::new

Page 34: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Beyond theMyths

Page 35: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Claim: Syntax is the mostimportant thing aboutLambda Expressions

Page 36: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Yeah, I liked the # syntax proposal better,too. One less character to type! :)

Page 37: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Have you considered 'default null'? It willsave a keyword

Page 38: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

How about a single punctuation mark,currently unused, as syntax sugar for "()-

>".

Page 39: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

(_, _) -> _ + _

This is starting to look like risque ASCII art:)

Page 40: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Its a Myth!

Page 41: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Claim: Syntax is irrelevant

Page 42: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

// Originally invalidStream.of(1, 2, 3) .forEach(x -> System.out.println(x));

// Required extra ;Stream.of(1, 2, 3) .forEach(x -> System.out.println(x););

Page 43: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Difference betweenexpectations

Many language features stolen! adapted

Missing Features

Stronger Type System

Tuples

List construction syntax

Page 44: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Framing EffectDifferent reactions depending on whether something is

presented as a loss or a gain.

Page 45: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Recall our earlier exampleList<String> origins = album.getMusicians() .filter(artist -> artist.getName().startsWith("The")) .map(artist -> artist.getNationality()) .collect(toList());

Page 46: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Eager vs Lazy (2) album.getMusicians() .filter(artist -> artist.getName().startsWith("The")) .map(artist -> artist.getNationality())

// What's happened? .collect(toList());

Page 47: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Very little TestingMaybe ...

a reflection on popularity of TDD

spikes are good for learning

unfamiliarity with testing lambdas

Page 48: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

How do I test this?list.stream() .map(x -> 1.0 / Math.ceil(1 + Math.pow(x) + Math.atan2(y, x))) .collect(toList());

Page 49: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Approach 1: Testsurrounding methodDon't test the lambda

Test the method its surrounded by

Works well for simple lambdas

Page 50: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Approach 2: ExtractMethod

double complexFunction(double x) { return 1.0 / Math.ceil(1 + Math.pow(x) + Math.atan2(0, x));}

list.stream() .map(this::complexFunction) .collect(toList());

Page 51: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Mistake: debugging// Streamslist.stream() .filter(filteringFunction) .map(mappingFunction) .collect(toList());

// Ye olde for loopList<Bar> bars = new ArrayList<>();for (Foo element : list) { if (filteringFunction(element) { Bar result = mappingFunction(element); bars.add(result); }}

Page 52: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

peeklist.stream() .filter(filteringFunction) .peek(e -> System.out.println("Filtered value: " + e)); .map(mappingFunction) .map(e -> e); .collect(toList());

Page 53: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Compiler Error Messages

Page 54: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

ComparatorsComparator<String> comparator = comparing(String::length);

Comparator<String> comparator = comparing(str -> str.length);

Page 55: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Compiler Errorjava: reference to comparing is ambiguous bothmethod<T>comparing(java.util.function.ToIntFunction< ? super T>)in java.util.Comparator and method<T,U>comparing(java.util.function.Function< ? super T,? extends U>)in java.util.Comparator match

Page 56: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

What happened?// Generic object variantpublic static <T, U extends Comparable< ? super U>> Comparator<T> comparing(Function< ? super T, ? extends U> keyExtractor)

// Specialised primitive variantpublic static <T> Comparator<T> comparing(ToIntFunction< ? super T> keyExtractor)

Page 57: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

SummarySyntax important, but not in the way

people think

New approaches for debugging and

testing

Take care of overloads and compiler

error messages

Page 58: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

FunctionalThinking

Page 59: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

FunctionalThinking?

Thinking in terms of the input to output relationship andnot a sequence of steps

Page 60: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

First code that peoplewrite

List<Integer> numbers = Arrays.asList(1, 2, 3);numbers.forEach(x -> { System.out.println(x);});

Page 61: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Non-idiomatic ProposalsEg: capture non-final local variables

Page 62: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Example ProblemCount the number of instances of each word in a

document.

Page 63: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Ideal Solutionreader.lines() .flatMap(s -> s.splitAsStream(" ")) .collect(groupingBy(s -> s, counting()));

Page 64: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Ideal Solution (then)reader.lines() .flatMap(s -> Stream.of(s.split(" "))) .collect(groupingBy(s -> s, reducing(s -> 1, Integer::sum)));

// Map entries for "dad"// [ "dad", "dad", "dad" ] => [1, 1, 1] => 3

Page 65: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Bad Solution (Part 1)Map<String, List<String>> initial = br.lines() .flatMap(s -> Arrays.stream(s.split(" "))) .collect(groupingBy(s -> s)); Map<Map.Entry<String, Integer>, Integer> freq1 = initial .entrySet().stream() .map(entry -> new AbstractMap.SimpleImmutableEntry<String,Integer>(entry.getKey(), entry.getValue().size())) .collect(Collectors.toMap(entry -> entry.getValue()));

Page 66: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Bad Solution (Part 2) Supplier<HashMap<String, Integer>> supplier = () -> newHashMap<String, Integer>(); BiConsumer<HashMap<String, Integer>, Map.Entry<String, Integer>> accum = (HashMap<String, Integer> result, Map.Entry<String, Integer>entry) -> result.put(entry.getKey(), entry.getValue()); BiConsumer<HashMap<String, Integer>, HashMap<String, Integer>>merger = HashMap::putAll;

Map<String, Integer> freq2 = initial.entrySet().stream() .map(entry -> new AbstractMap.SimpleImmutableEntry<String,Integer>(entry.getKey(), entry.getValue().size())) .collect(supplier, accum, merger);

Page 67: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

This takes thought

Page 68: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

SummaryIdioms are vital

Not Java specific at all

Requires Practise

Page 69: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

ConclusionsGone through a bunch of examples of

specific issues

‘Functional Thinking’: Not necessary to

start learning.

Try before you buy

Page 70: Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)

Questions?@RichardWarburtohttp://jclarity.com

http://insightfullogic.com

https://github.com/RichardWarburton/