javaslang @ devoxx

Post on 15-Feb-2017

348 Views

Category:

Engineering

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

#Devoxx #Javaslang @koenighotze

JΛVΛSLΛNGFunctional Sugar For Java

#Devoxx #Javaslang @koenighotze

Senacor Technologies Programmer!

That’s me coding Scala

David Schmitz / @koenighotzeSenacor Technologies

Programmer! That’s me coding Scala

#Devoxx #Javaslang @koenighotze

What’s in it for you?Functional programming is hip

How Javaslang helped us

Examples, Code!

#Devoxx #Javaslang @koenighotze

Functors, applicatives,

monads and friends stay home

#Devoxx #Javaslang @koenighotze

Code that is easier to reason about

#Devoxx #Javaslang @koenighotze

Side-effects are eviltry { int i = 1/0; } catch (Throwable t) { … }Exceptions are goto-statements

:(

#Devoxx #Javaslang @koenighotze

Referential TransparencyMath.random();

Math.max(1, 2);

Math.random();

Math.max(1, 2);

Pure functions are a Good ThingTm

:(

#Devoxx #Javaslang @koenighotze

Thinking in ValuesImmutability

Performance

Safety

#Devoxx #Javaslang @koenighotze

In a nutshell, think about “what to code“

not “how to code”

#Devoxx #Javaslang @koenighotze

Enter Java 8(a) -> a + 2

list.stream().filter…

Excitement…

#Devoxx #Javaslang @koenighotze

“Try filtering all invalid users from a list of users”

#Devoxx #Javaslang @koenighotze

Excitement?…untilusers.stream() .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());

#Devoxx #Javaslang @koenighotzePainting by Gustav Courbet

#Devoxx #Javaslang @koenighotze

import static javaslang.API.*;

+

#Devoxx #Javaslang @koenighotze

What we’ll coverImmutable collections

Some functional sugar

Pattern matching

#Devoxx #Javaslang @koenighotze

Before we get to the details… Let’s fix that ugly code

#Devoxx #Javaslang @koenighotze

Fixing Things….users.stream() .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());

#Devoxx #Javaslang @koenighotze

Functional collectionsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());

#Devoxx #Javaslang @koenighotze

No need for CollectorsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());

#Devoxx #Javaslang @koenighotze

No need for CollectorsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}); .collect(Collectors.toList());

#Devoxx #Javaslang @koenighotze

Wrapping ExceptionsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}); .collect(Collectors.toList());

#Devoxx #Javaslang @koenighotze

Wrapping ExceptionsList.ofAll(users) .filter(user ->

Try.of(user::validateAddress) .getOrElse(false) ); } catch (IllegalStateException ex) { return ); .collect(Collectors.toList();

#Devoxx #Javaslang @koenighotze

List.ofAll(users) List.filter(user -> Try.of(user::validateAddress) .getOrElse(false));

“Try filtering all invalid users from a list of users”

#Devoxx #Javaslang @koenighotze

Immutable Collections Image by Douglas Muth, https://flic.kr/p/acFwxG

#Devoxx #Javaslang @koenighotze

Mutable Collections are Evil

Returning void == Side-Effect!

interface Collection<E> { … void clear(); }

interface Collection<E> { … void clear(); }

#Devoxx #Javaslang @koenighotze

Easy solution? Collections

Collections .unmodifiableList(list); .add("BUMM");

#Devoxx #Javaslang @koenighotze

Easy solution? Collections

Collections .unmodifiableList(list) .add("BUMM");

#Devoxx #Javaslang @koenighotze

#Devoxx #Javaslang @koenighotze

Javaslang CollectionsList<~> t = List.of(“F95”);

List<~> t2 = t.append(withName(“FCK”));

F95 /t

#Devoxx #Javaslang @koenighotze

ImmutableList<~> t = List.of(“F95”);

List<~> t2 = t.prepend(“FCK”);

F95 /t

FCKt2

#Devoxx #Javaslang @koenighotze

List<~> t = List.of(“F95”);

List<~> t2 = t.prepend(“FCK”);

F95 /

FCK

t

t2

Persistent and Efficient

#Devoxx #Javaslang @koenighotze

Streams are glorified IteratorsStream<String> jdk = Stream.of("a", “B");

jdk.map(String::toUpperCase); jdk.map(String::toLowerCase);

#Devoxx #Javaslang @koenighotze

java.lang.IllegalStateException: stream has already been operated upon or closed at java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203) at java.util.stream.ReferencePipeline.<init>(ReferencePipeline.java:94) at java.util.stream.ReferencePipeline$StatelessOp.<init>(ReferencePipeline.java:618) at java.util.stream.ReferencePipeline$3.<init>(ReferencePipeline.java:187) at java.util.stream.ReferencePipeline.map(ReferencePipeline.java:186)

#Devoxx #Javaslang @koenighotze

Javaslang StreamsStream<String> slang = Stream.of("a", "B"); slang.map(String::toUpperCase); // “A”,“B” slang.map(String::toLowerCase); // “a”,“b”

#Devoxx #Javaslang @koenighotze

Javaslang StreamsStream<String> slang = Stream.of("a", "B"); slang.map(String::toUpperCase) .take(2); slang.map(String::toLowerCase) .take(2);

#Devoxx #Javaslang @koenighotze

Javaslang StreamsStream<String> slang = Stream.of("a", "B"); slang.map(String::toUpperCase) .take(2);// “A”,“B” slang.map(String::toLowerCase) .take(2);// “a”,“b”

#Devoxx #Javaslang @koenighotze

Functional data structures improve performance and

reduce the chance of unexpected behaviour

#Devoxx #Javaslang @koenighotze

Functional Sugar

#Devoxx #Javaslang @koenighotze

“Find a user and, if an address is available, fetch

the user’s street”

#Devoxx #Javaslang @koenighotze

Cascading Pile of ShameUser user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

#Devoxx #Javaslang @koenighotze

We’ve got java.util.Optional

Optional<User> opt = Optional.ofNullable(user);

if (optional.isPresent()) { … }

#Devoxx #Javaslang @koenighotze

#Devoxx #Javaslang @koenighotze

Please stop usingOptional#isPresent()

#Devoxx #Javaslang @koenighotze

An Option is like a Gift Box

NoneSome

#Devoxx #Javaslang @koenighotze

Map opens the Gift Box

MapSome Some

( )->

#Devoxx #Javaslang @koenighotze

Nothing from Nothing( )->

MapNone None

#Devoxx #Javaslang @koenighotze

Optional or Option?

Optional

#Devoxx #Javaslang @koenighotze

Optional or Option?

Option

Some None

#Devoxx #Javaslang @koenighotze

Optional or Option?

Option

Some None

Value

Iterable

#Devoxx #Javaslang @koenighotze

Optional or Option?

Option

Some None

Value

Iterable

#Devoxx #Javaslang @koenighotze

Optional or Option?

Option

Some None

Value

Iterable

Serializable

#Devoxx #Javaslang @koenighotze

Fixing the Pile of ShameUser user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

#Devoxx #Javaslang @koenighotze

Option all the ThingsUser user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

Option<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } } Option<Address> getAddress()

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); .map(Address::getStreet)

return address.getStreet(); } }

#Devoxx #Javaslang @koenighotze

repo.findOne("id") .flatMap(User::getAddress) .map(Address::getStreet) .getOrElse("");

“Find a user and, if an address is available, fetch the user’s street”

#Devoxx #Javaslang @koenighotze

Option and map transform nested code into an

understandable story

#Devoxx #Javaslang @koenighotze

Working with legacy codePainting by Eero Järnefelt

#Devoxx #Javaslang @koenighotze

Nice Validation Codepublic static String check(String iban){ if (validationMagic(iban)) { return iban; }

throw new IllegalArgumentException(“Peng”); }

#Devoxx #Javaslang @koenighotze

Awesome WTF Code String iban; try { iban = check("AL47"); } catch (IllegalArgumentException ex) { iban = ""; }

#Devoxx #Javaslang @koenighotze

From Exceptions to Options

String iban = lift(Iban::check) .apply("AL47...") .getOrElse("");

#Devoxx #Javaslang @koenighotze

From Exceptions to Options

String iban = lift(Iban::check) .apply("AL47...") .getOrElse("");

#Devoxx #Javaslang @koenighotze

Wrapping Exceptions with Try

Try.of(() -> stuffToDo())

#Devoxx #Javaslang @koenighotze

Wrapping Exceptions with Try

FailureException

SuccessResult

Try.of(() -> stuffToDo())

#Devoxx #Javaslang @koenighotze

Exceptions to Options with Try

Try.of(() -> check("AL..")) .getOrElse("")

#Devoxx #Javaslang @koenighotze

Exceptions to Options with Try

Try.of(() -> check("AL..")) .getOrElse("")

#Devoxx #Javaslang @koenighotze

Lifting and Try-ing reduce exception handling clutter

and side-effects

#Devoxx #Javaslang @koenighotze

Structural DecompositionImage by Arend, https://flic.kr/p/pkBe4g

#Devoxx #Javaslang @koenighotze

Classic HTTP Handlingif (OK.equals(res.getStatusCode())) { return res.getBody(); }

return emptyList();

#Devoxx #Javaslang @koenighotze

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Pattern Matching Basics

#Devoxx #Javaslang @koenighotze

Pattern Matching Basics

Match(expression) .of(cases)

#Devoxx #Javaslang @koenighotze

Cases map functions to patterns

Case(pattern, function)

#Devoxx #Javaslang @koenighotze

Example Patterns

$() wildcard pattern $(“foo”) equals pattern isIn(“a”, “b”) conditional pattern

#Devoxx #Javaslang @koenighotze

HTTP Handling Fixed

*Note: some type details missing

Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

#Devoxx #Javaslang @koenighotze

Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

HTTP Handling Fixed

*Note: some type details missing

OK or anything else

#Devoxx #Javaslang @koenighotze

HTTP Handling Fixed

*Note: some type details missing

Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

#Devoxx #Javaslang @koenighotze

HTTP Handling Fixed

*Note: some type details missing

Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

#Devoxx #Javaslang @koenighotze

HTTP Handling FixedMatch(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

*Note: some type details missing

#Devoxx #Javaslang @koenighotze

Matching a Try

public Try<…> fetchFromUrl(…) { … }

#Devoxx #Javaslang @koenighotze

Matching a TryMatch(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );

#Devoxx #Javaslang @koenighotze

Matching a TryMatch(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );

#Devoxx #Javaslang @koenighotze

Matching a TryMatch(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );

#Devoxx #Javaslang @koenighotze

Presto!Match(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );

#Devoxx #Javaslang @koenighotze

Pattern matching replaces complex if-then-else sequences

with clear expressions

#Devoxx #Javaslang @koenighotze

HashMap.of("Foo", "Bar", "Qux", "Baz") .bimap(String::toLowerCase, String::toUpperCase) .get("qux"); // BAZ

Javaslang offers much more

#Devoxx #Javaslang @koenighotze

Javaslang offers much moreTuple.of("Foo", 1) .map((s, i) -> Tuple.of(s + "Bar", i + 5)) // “FooBar”, 6

#Devoxx #Javaslang @koenighotze

Javaslang offers much more

#Devoxx #Javaslang @koenighotze

So, is this is the mother of all free lunches?

#Devoxx #Javaslang @koenighotze

What are the drawbacks?

#Devoxx #Javaslang @koenighotze

What are the drawbacks?count(Collection-libs)

>

count(Logging-libs)

#Devoxx #Javaslang @koenighotze

What are the drawbacks?Option.of(foo)

.map

.filter

.flatMap

#Devoxx #Javaslang @koenighotze

Wrapping upSlick, stable, consistent API

Object-functional

Complex(?)

Version 3 in 2017

#Devoxx #Javaslang @koenighotze

.iohttp://

Do you want to know more?

#Devoxx #Javaslang @koenighotze

Thank You!<david.schmitz@senacor.com>

top related