it's java jim, but not as we know it!

Post on 03-Mar-2017

235 Views

Category:

Software

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

© 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

top related