View
241
Download
1
Category
Preview:
Citation preview
© Copyright Azul Systems 2017
© Copyright Azul Systems 2015
@speakjavaazul.com
It’s Java, Jim, But Not As We Know It!
Simon RitterDeputy CTO, Azul Systems
1
© Copyright Azul Systems 2017
Agenda Java Lambda expressions Lambda expression performance How far can we take lambdas? Summary
2
© Copyright Azul Systems 2017
Java Lambda Expressions
© Copyright Azul Systems 2017
JDK 8 Lambda Expressions Simplified representation of behaviour in Java
– Anonymous inner class is clunky Assign to variable, pass as parameter Use wherever the type is a Functional Interface
– Much simpler than adding a function type to Java– Single abstract method– Not necessarily single method
default and static methods don’t count
4
© Copyright Azul Systems 2017
Lambda Expression Syntax Like a method
– But not associated with a class– Typed parameters, body, return type, exceptions
Closure over values, not types– Only capture effectively-final variables
5
(parameters) -> body
Lambda operator
© Copyright Azul Systems 2017
Capturing Lambdas
6
class DataProcessor { private int currentValue;
public void process() { DataSet myData = myFactory.getDataSet(); dataSet.forEach(d -> d.use(currentValue++)); }}
© Copyright Azul Systems 2017
Capturing Lambdas
7
class DataProcessor { private int currentValue;
public void process() { DataSet myData = myFactory.getDataSet(); dataSet.forEach(d -> d.use(this.currentValue++));
}}
Reference to this insertedby compiler
© Copyright Azul Systems 2017
Method References Method references let us reuse a method as a lambda
expression
FileFilter x = File f -> f.canRead();
FileFilter x = File::canRead;
© Copyright Azul Systems 2017
Method References Format: target_reference::method_name Three kinds of method reference
– Static method– Instance method of an arbitrary type– Instance method of an existing object
9
© Copyright Azul Systems 2017
Method References
10
Lambda
Method Ref
Lambda
Method Ref
Lambda
Method Ref
(args) -> ClassName.staticMethod(args)
(arg0, rest) -> arg0.instanceMethod(rest)
(args) -> expr.instanceMethod(args)
ClassName::staticMethod
ClassName::instanceMethod
expr::instanceMethod
Rules For Construction
© Copyright Azul Systems 2017
Method References
(String s) -> Integer.parseInt(s);
(String s, int i) -> s.substring(i)
Axis a -> getLength(a)
Integer::parseInt
String::substring
this::getLength
Lambda
Method Ref
Lambda
Method Ref
Lambda
Method Ref
Examples
© Copyright Azul Systems 2017
Lambda Expression Performance
© Copyright Azul Systems 2017
Lambdas & Anonymous Inner Classes Functionally equivalent
13
myList.forEach(w -> System.out.println(w));
myList.forEach(new Consumer<String>() { @Override public void accept(String w) { System.out.println(w); }});
myList.forEach(System.out::println);
© Copyright Azul Systems 2017
Anonymous Inner Classes As the name suggests, we are dealing with classes
– Compiler generates class with name like Foo$1– Type pollution
The class must be loaded at run time Instantiated like any other class Lambda expressions could be implemented this way
– Originally they were– Forces an inner class where you didn’t ask for it
You wanted a function
14
© Copyright Azul Systems 2017
Lambda Implementation A better answer: invokedynamic
– Introduced in Java SE 7 to improve performance of dynamically typed languages running on the JVM
– Defers implementation of the Lambda to runtime Lambda compilation
– Generate invokedynamic call (lambda factory) java.lang.LambdaMetaFactory Return instance of (lambda) functional interface type
– Convert body of lambda to method Not necessary for method references
15
© Copyright Azul Systems 2017
Lambda Implementation Non-capturing Lambda
– Simple conversion to static method in the class where the lambda is used
Capturing Lambdas– Static method with captured variables prepended as
parameters– Synthetic instance method of class using Lambda
Lambda invokes a class method
16
© Copyright Azul Systems 2017
Implementation Differences Lambdas
– Linkage (CallSite)– Capture– Invocation
17
Anonymous inner classes– Class loading– Instantiation– Invocation
Non-capturing lambdas automatically optimise Method references are slightly more optimal -XX:+TieredCompilation gives better Lambda
results– Advice is don’t use -XX:-TieredCompilation
© Copyright Azul Systems 2017
How Far Can We Take Lambdas?
With inspiration from Jarek Ratajski
© Copyright Azul Systems 2017 19
Alonso Church
The λ Calculus (1936)
What does this have to do with Java?
© Copyright Azul Systems 2017
Exploding Head Lambdas Java programmers are typically imperative programmers Functional programming is not imperative
– As we’ll see Lambda Calculus and Turing Machines are equivalent But will give you a headache
– At least it did me! What can we do only using Lambda expressions?
– And one functional interface
20
© Copyright Azul Systems 2017
Functional Interface
@FunctionalInterfacepublic interface Lambda { Lambda apply(Lambda lambda);}
© Copyright Azul Systems 2017
Function Basics Identity [ λx.x ]
Lambda identity = x -> x;
Lambda identity = new Lambda { Lambda apply(Lambda x) { return x; }};
© Copyright Azul Systems 2017
Function Basics (Booleans) Boolean false [ λf.λx.x ]
boolFalse = f -> (x -> x); // Always returns identity
boolFalse = new Lambda { Lambda apply(Lambda f) { return new Lambda { Lambda apply(Lambda x) { return x; } }}};
© Copyright Azul Systems 2017
Function Basics (Booleans) Boolean true [ λf.λx.f ]
boolTrue = f -> (x -> f); // Never returns identity
boolTrue = new Lambda { Lambda apply(Lambda f) { return new Lambda { Lambda apply(Lambda x) { return f; } }}};
© Copyright Azul Systems 2017
Church Numerals Zero [ λf.λx.x ]
• Identity for addition and subtraction (a ± 0 = a)• The Lambda is the same as false• The function is applied zero times to the argument
zero = f -> x -> x; One [ λf.λx.(f x) ] one = f -> x -> f.apply(x);
Two [ λf.λx.(f (f x)) ] two = f -> x -> f.apply(f.apply(x));
25
© Copyright Azul Systems 2017
Church Encoding Successor: n++ [ λn.λf.λx.f(n f x) ] successor = n -> f -> x -> f.apply(n.apply(f).apply(x));
26
© Copyright Azul Systems 2017
Church Encoding Predecessor: n--
27
predecessor = n -> f -> x -> n.apply(g -> h -> h.apply(g.apply(f))) .apply(u -> x).apply(u -> u);
[ λn.λf.λx.n(λg.λh.h(g f))(λu.x)(λu.u) ]
© Copyright Azul Systems 2017
Church Encoding Add: m + n [ λm.λn.λf.λx ((m f) ((n f) x)) ] m -> n -> f -> x -> m.apply(f).apply(n.apply(f).apply(x))
Subtract: m - n [ λm.λn.(n predecessor) m ] m -> n -> m.apply(predecessor).apply(n)
28
© Copyright Azul Systems 2017
Solving 2 + 2 With Lambdas
Lambda two = f -> x -> f.apply(f.apply(x));
Lambda plus = m -> n -> f -> x -> m.apply(f).apply(n.apply(f).apply(x));
Lambda four = plus.apply(two).apply(two);
4 = + 2 2 (Polish notation)
© Copyright Azul Systems 2017
Solving 2 + 2 With Lambdasm -> n -> f -> x -> m.apply(f).apply(n.apply(f).apply(x))
n -> f -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(n.apply(f).apply(x))
© Copyright Azul Systems 2017
Solving 2 + 2 With Lambdasm -> n -> f -> x -> m.apply(f).apply(n.apply(f).apply(x))
n -> f -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(n.apply(f).apply(x))
f -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(f -> x -> f.apply(f.apply(x).apply(f).apply(x))
© Copyright Azul Systems 2017
Solving 2 + 2 With Lambdasf -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(f -> x -> f.apply(f.apply(x)).apply(f).apply(x))f -> x -> x -> f.apply(f.apply(x)) .apply(f -> x -> f.apply(f.apply(x)).apply(f).apply(x))
© Copyright Azul Systems 2017
Solving 2 + 2 With Lambdasf -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(f -> x -> f.apply(f.apply(x)).apply(f).apply(x))f -> x -> x -> f.apply(f.apply(x)) .apply(f -> x -> f.apply(f.apply(x)).apply(f).apply(x))f -> x -> x -> f.apply(f.apply(x)) .apply(x -> f.apply(f.apply(x)).apply(x))
© Copyright Azul Systems 2017
Solving 2 + 2 With Lambdasf -> x -> x -> f.apply(f.apply(x)) .apply(x -> f.apply(f.apply(x)).apply(x))
f -> x -> x -> f.apply(f.apply(x)) .apply(f.apply(f.apply(x)))
f -> x -> x -> f.apply(f.apply(x)) .apply(f.apply(f.apply(x)))
f -> x -> f.apply(f.apply(f.apply(f.apply(x)))= 4!
© Copyright Azul Systems 2017
Summary
© Copyright Azul Systems 2017
Lambda Expressions Very useful and powerful
– Succinct way to parameterise behaviour Better performance than anonymous inner class
– Invokedynamic implementation Can be used in weird and wonderful ways
– Not necessarily to be recommended!
36
© Copyright Azul Systems 2017
More Information Dixin Yan’s blog
– weblogs.asp.net/dixin (C# based, but useful)– October 2016
Jarek’s presentation from Voxxed Zurich– https://www.youtube.com/watch?v=Dun8ewSeX6c
37
© Copyright Azul Systems 2017
© Copyright Azul Systems 2015
@speakjavaazul.com
It’s Java, Jim, But Not As We Know It!
Simon RitterDeputy CTO, Azul Systems
38
Recommended