Lambdas:
Myths and
Mistakes
by Richard Warburton
Learning FP is so much more than just
knowing what map/fold/filter/etc. do. It's
more like getting good at Portal :)
@copu...
Who am I?
Currently work at jClarity
Focus on performance diagnostics and
static analysis
Adopt a JSR (Date and Time + Lam...
Talk Structure
Background and Motivation
Introduction to Lambda Expressions
Beyond the Myths
Functional Thinking
Background
and Motvation
Lambda Expressions are
coming in Java 8!
Lots of discussion/debate
How can we help?
Adopt-a-JSR
Adopt-a-JSR?
Community driven standards feedback
Hackdays
Serve on Expert Groups
Initiated by Martijn Verburg
Some discussion
unimportant
Concrete Examples focus discussion
Introduction
to Lambda
Expressions
Overview of Lambdas
Goal: Better Libraries
Example: Data Parallelism
Approach: Allow Code as Data
Action Listener
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.ou...
Code as Data
button.addActionListener(
?
);
Need a parameter
button.addActionListener(event
);
Lambda Example
button.addActionListener(event ->
System.out.println("button clicked")
);
No parameters
Runnable helloWorld =
() -> System.out.println("Hello World");
Variable Capture
String name = getUserName();
button.addActionListener(event ->
System.out.println("hi " + name)
);
Functional Interfaces
Everything in Java has a type
Problem: Need types to represent
Functions
Solution: Use interfaces
Functional Interfaces
public interface ActionListener extends EventListener {
public void actionPerformed(ActionEvent even...
Functional Interfaces
Want to support automated Data
Parallelism
Construct for building computation
pipelines
Iterator wit...
External Iteration
int count = 0;
for (Artist artist : artists) {
if (artist.isFrom("London")) {
count++;
}
}
Internal Iteration
artists.stream()
.filter(artist -> artist.isFrom("London"));
map
map
List<String> collected = Stream.of("a", "b", "hello")
.map(string -> string.toUpperCase())
.collect(toList());
assertE...
reduce
reduce
int count = Stream.of(1, 2, 3)
.reduce(0, (acc, x) -> acc + 1);
assertEquals(3, count);
filter
filter
List<String> beginningWithNumbers =
Stream.of("a", "1abc", "abc1")
.filter(value -> isDigit(value.charAt(0)))
.coll...
Putting it all together
for a given an album, find the nationality of every band
playing on that album
Putting it all together (2)
1. transform an album into its artists
2. figure out which artists are bands
3. find the natio...
Putting it all together (3)
List<String> origins =
album.getMusicians()
.filter(artist -> artist.getName().startsWith("The...
Method References
str -> str.length
String::length
x -> foo.bar(x)
foo::bar
str -> new Name(str)
Name::new
Beyond the
Myths
Claim: Syntax is the most
important thing about
Lambda Expressions
Yeah, I liked the # syntax proposal better,
too. One less character to type! :)
Have you considered 'default null'? It will
save a keyword
How about a single punctuation mark,
currently unused, as syntax sugar for "()-
>".
(_, _) -> _ + _
This is starting to look like risque ASCII art
:)
Its a Myth!
Claim: Syntax is irrelevant
// Originally invalid
Stream.of(1, 2, 3)
.forEach(x -> System.out.println(x));
// Required extra ;
Stream.of(1, 2, 3)
.for...
Difference between
expectations
Many language features stolen! adapted
Missing Features
Stronger Type System
Tuples
List c...
Framing Effect
Different reactions depending on whether something is
presented as a loss or a gain.
Recall our earlier example
List<String> origins =
album.getMusicians()
.filter(artist -> artist.getName().startsWith("The"...
Eager vs Lazy (2)
album.getMusicians()
.filter(artist -> artist.getName().startsWith("The"))
.map(artist -> artist.getNati...
Eager vs Lazy (3)
album.getMusicians()
.filter(artist -> artist.getName().startsWith("The"))
.map(artist -> artist.getNati...
Very little TDD
Only a couple of developers used TDD or
unit tests
Maybe a reflection on general TDD
Maybe unfamiliarity w...
How do I test this?
list.stream()
.map(x -> 1.0 / Math.ceil(1 + Math.pow(x) + Math.atan2(0, x)))
.collect(toList());
Approach 1: Test
surrounding function
Don't test the lambda
Test the method its surrounded by
Works well for simple lambdas
Approach 2: Extract
Method
double complexFunction(double x) {
return 1.0 / Math.ceil(1 + Math.pow(x) + Math.atan2(0, x));
...
Mistake: debugging
list.stream()
.filter(filteringFunction)
.map(mappingFunction)
.collect(toList());
List<Bar> bars = new...
peek
list.stream()
.filter(filteringFunction)
.peek(e -> System.out.println("Filtered value: " + e));
.map(mappingFunction...
Compiler Error Messages
Comparators
Comparator<String> comparator = comparing(String::length);
Comparator<String> comparator = comparing(str -> st...
Compiler Error
java: reference to comparing is ambiguous both
method
<T>comparing(java.util.function.ToIntFunction< ? supe...
What happened?
// Generic object variant
public static <T, U extends Comparable< ? super U>>
Comparator<T>
comparing(Funct...
Summary
Syntax important, but not in the way
people think
New approaches for debugging and
testing
Take care of overloads ...
Functional
Thinking
Functional
Thinking?Thinking in terms of the input to output relationship and
not a sequence of steps
First code that people
write
List<Integer> numbers = Arrays.asList(1, 2, 3);
numbers.forEach(x -> {
System.out.println(x);...
Non-idiomatic Proposals
Eg: capture non-final local variables
Example Problem
Count the number of instances of each word in a
document.
Example Problem
Ideal Solution
reader.lines()
.flatMap(s -> Stream.of(s.split(" ")))
.collect(groupingBy(s -> s, counting()));
Ideal Solution (then)
reader.lines()
.flatMap(s -> Stream.of(s.split(" ")))
.collect(groupingBy(s -> s, reducing(s -> 1, I...
Bad Solution (Part 1)
Map<string, list<string="">> initial
= br.lines()
.flatMap(s -> Arrays.stream(s.split(" ")))
.collec...
Bad Solution (Part 2)
Supplier<hashmap<string, integer="">> supplier = () -> new
HashMap<string, integer="">();
BiConsumer...
Summary
Functional Thinking the most important
thing to learn
Not Java specific at all
Requires Practise
Conclusions
Gone through a bunch of examples of
specific issues
‘Functional Thinking’: Not necessary to
start learning.
Tr...
Questions?@RichardWarburto
http://insightfullogic.com
https://github.com/RichardWarburton/
Upcoming SlideShare
Loading in …5
×

Lambdas: Myths and Mistakes

1,582 views

Published on

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?
* What mistakes does a developer make?
* Can a ‘blue collar’ Java Developer cope with functional programming?
* Can we avoid these mistakes in future?

In London we’ve been running a series of hackdays trying out Lambda Expressions as part of the Adopt-a-JSR program and have been recording and analysing the results. This gives us unprecedented insight into what will happen in future.

Published in: Technology, News & Politics
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,582
On SlideShare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
44
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Lambdas: Myths and Mistakes

  1. 1. Lambdas: Myths and Mistakes by Richard Warburton
  2. 2. Learning FP is so much more than just knowing what map/fold/filter/etc. do. It's more like getting good at Portal :) @copumpkin
  3. 3. Who am I? Currently work at jClarity Focus on performance diagnostics and static analysis Adopt a JSR (Date and Time + Lambdas) Writing a book for O'Reilly Media on Lambda Expressions in Java 8.
  4. 4. Talk Structure Background and Motivation Introduction to Lambda Expressions Beyond the Myths Functional Thinking
  5. 5. Background and Motvation
  6. 6. Lambda Expressions are coming in Java 8!
  7. 7. Lots of discussion/debate
  8. 8. How can we help? Adopt-a-JSR
  9. 9. Adopt-a-JSR? Community driven standards feedback Hackdays Serve on Expert Groups Initiated by Martijn Verburg
  10. 10. Some discussion unimportant Concrete Examples focus discussion
  11. 11. Introduction to Lambda Expressions
  12. 12. Overview of Lambdas Goal: Better Libraries Example: Data Parallelism Approach: Allow Code as Data
  13. 13. Action Listener button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { System.out.println("button clicked"); } });
  14. 14. Code as Data button.addActionListener( ? );
  15. 15. Need a parameter button.addActionListener(event );
  16. 16. Lambda Example button.addActionListener(event -> System.out.println("button clicked") );
  17. 17. No parameters Runnable helloWorld = () -> System.out.println("Hello World");
  18. 18. Variable Capture String name = getUserName(); button.addActionListener(event -> System.out.println("hi " + name) );
  19. 19. Functional Interfaces Everything in Java has a type Problem: Need types to represent Functions Solution: Use interfaces
  20. 20. Functional Interfaces public interface ActionListener extends EventListener { public void actionPerformed(ActionEvent event); }
  21. 21. Functional Interfaces Want to support automated Data Parallelism Construct for building computation pipelines Iterator with inversion of control
  22. 22. External Iteration int count = 0; for (Artist artist : artists) { if (artist.isFrom("London")) { count++; } }
  23. 23. Internal Iteration artists.stream() .filter(artist -> artist.isFrom("London"));
  24. 24. map
  25. 25. map List<String> collected = Stream.of("a", "b", "hello") .map(string -> string.toUpperCase()) .collect(toList()); assertEquals(asList("A", "B", "HELLO"),collected);
  26. 26. reduce
  27. 27. reduce int count = Stream.of(1, 2, 3) .reduce(0, (acc, x) -> acc + 1); assertEquals(3, count);
  28. 28. filter
  29. 29. filter List<String> beginningWithNumbers = Stream.of("a", "1abc", "abc1") .filter(value -> isDigit(value.charAt(0))) .collect(toList()); assertEquals(asList("1abc"), beginningWithNumbers);
  30. 30. Putting it all together for a given an album, find the nationality of every band playing on that album
  31. 31. Putting it all together (2) 1. transform an album into its artists 2. figure out which artists are bands 3. find the nationalities of each band
  32. 32. Putting it all together (3) List<String> origins = album.getMusicians() .filter(artist -> artist.getName().startsWith("The")) .map(artist -> artist.getNationality()) .collect(toList());
  33. 33. Method References str -> str.length String::length x -> foo.bar(x) foo::bar str -> new Name(str) Name::new
  34. 34. Beyond the Myths
  35. 35. Claim: Syntax is the most important thing about Lambda Expressions
  36. 36. Yeah, I liked the # syntax proposal better, too. One less character to type! :)
  37. 37. Have you considered 'default null'? It will save a keyword
  38. 38. How about a single punctuation mark, currently unused, as syntax sugar for "()- >".
  39. 39. (_, _) -> _ + _ This is starting to look like risque ASCII art :)
  40. 40. Its a Myth!
  41. 41. Claim: Syntax is irrelevant
  42. 42. // Originally invalid Stream.of(1, 2, 3) .forEach(x -> System.out.println(x)); // Required extra ; Stream.of(1, 2, 3) .forEach(x -> System.out.println(x););
  43. 43. Difference between expectations Many language features stolen! adapted Missing Features Stronger Type System Tuples List construction syntax
  44. 44. Framing Effect Different reactions depending on whether something is presented as a loss or a gain.
  45. 45. Recall our earlier example List<String> origins = album.getMusicians() .filter(artist -> artist.getName().startsWith("The")) .map(artist -> artist.getNationality()) .collect(toList());
  46. 46. Eager vs Lazy (2) album.getMusicians() .filter(artist -> artist.getName().startsWith("The")) .map(artist -> artist.getNationality())
  47. 47. Eager vs Lazy (3) album.getMusicians() .filter(artist -> artist.getName().startsWith("The")) .map(artist -> artist.getNationality()) .collect(toList());
  48. 48. Very little TDD Only a couple of developers used TDD or unit tests Maybe a reflection on general TDD Maybe unfamiliarity with testing functional code
  49. 49. How do I test this? list.stream() .map(x -> 1.0 / Math.ceil(1 + Math.pow(x) + Math.atan2(0, x))) .collect(toList());
  50. 50. Approach 1: Test surrounding function Don't test the lambda Test the method its surrounded by Works well for simple lambdas
  51. 51. Approach 2: Extract Method double complexFunction(double x) { return 1.0 / Math.ceil(1 + Math.pow(x) + Math.atan2(0, x)); } list.stream() .map(this::complexFunction) .collect(toList());
  52. 52. Mistake: debugging list.stream() .filter(filteringFunction) .map(mappingFunction) .collect(toList()); List<Bar> bars = new ArrayList<>(); for (Foo element : list) { if (filteringFunction(element) { Bar result = mappingFunction(element); bars.add(result); } }
  53. 53. peek list.stream() .filter(filteringFunction) .peek(e -> System.out.println("Filtered value: " + e)); .map(mappingFunction) .map(e -> e); .collect(toList());
  54. 54. Compiler Error Messages
  55. 55. Comparators Comparator<String> comparator = comparing(String::length); Comparator<String> comparator = comparing(str -> str.length);
  56. 56. Compiler Error java: reference to comparing is ambiguous both method <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
  57. 57. What happened? // Generic object variant public static <T, U extends Comparable< ? super U>> Comparator<T> comparing(Function< ? super T, ? extends U> keyExtractor) // Specialised primitive variant public static <T> Comparator<T> comparing(ToIntFunction< ? super T> keyExtractor)
  58. 58. Summary Syntax important, but not in the way people think New approaches for debugging and testing Take care of overloads and compiler error messages
  59. 59. Functional Thinking
  60. 60. Functional Thinking?Thinking in terms of the input to output relationship and not a sequence of steps
  61. 61. First code that people write List<Integer> numbers = Arrays.asList(1, 2, 3); numbers.forEach(x -> { System.out.println(x); });
  62. 62. Non-idiomatic Proposals Eg: capture non-final local variables
  63. 63. Example Problem Count the number of instances of each word in a document.
  64. 64. Example Problem
  65. 65. Ideal Solution reader.lines() .flatMap(s -> Stream.of(s.split(" "))) .collect(groupingBy(s -> s, counting()));
  66. 66. 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
  67. 67. 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.ge .collect(Collectors.toMap(entry -> entry.getValue())); </string,></map.entry<string,></string,>
  68. 68. Bad Solution (Part 2) Supplier<hashmap<string, integer="">> supplier = () -> new HashMap<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.ge .collect(supplier, accum, merger); </string,></string,></string,></hashmap<string,></string,></str
  69. 69. Summary Functional Thinking the most important thing to learn Not Java specific at all Requires Practise
  70. 70. Conclusions Gone through a bunch of examples of specific issues ‘Functional Thinking’: Not necessary to start learning. Try before you buy
  71. 71. Questions?@RichardWarburto http://insightfullogic.com https://github.com/RichardWarburton/

×