java 8 and beyond, a scala story

24
Java 8 and Beyond , a Scala Story Tomer Gabel, April 2016

Upload: tomer-gabel

Post on 08-Jan-2017

437 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Java 8 and Beyond, a Scala Story

Java 8 and Beyond,a Scala StoryTomer Gabel, April 2016

Page 2: Java 8 and Beyond, a Scala Story

Preface

• Java 8 was released

in 2014

• Which begs the

question…

• Is Scala still relevant?

– Yes.

– This talk is about

convincing you!

Page 3: Java 8 and Beyond, a Scala Story

Quick Agenda

• A bit of history

– The Java-Scala gap

– How Java 8 reduces it

– Remaining gaps

• Showcase!

– Traits

– Pattern matching

– Implicits

Page 4: Java 8 and Beyond, a Scala Story

The Java-Scala gap

Historically (pre Java 8)

• Type inference

• Lambdas

• Traits

• Collections library

• DSLs

• Implicits

Page 5: Java 8 and Beyond, a Scala Story

The Java-Scala gap

Currently (with Java 8)

• Type inference

• Lambdas

• Traits

• Collections library

• DSLs

• Implicits

Page 6: Java 8 and Beyond, a Scala Story

There’s So Much More…

For-comprehensions

Flexible scoping

Built-in tuples

Higher-kinded types

Implicit conversions

Declaration-site

variance

(Partial) Functions

Bottom types

Structural types

Type members

Path-dependent types

Macros

Page 7: Java 8 and Beyond, a Scala Story

RIGHT. WHY SHOULD YOU CARE?

Page 8: Java 8 and Beyond, a Scala Story

SHOWCASE #1:TRAITS

Page 9: Java 8 and Beyond, a Scala Story

Ye Olde Logging

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

public class ClassWithLogs {

private static Logger log =

LoggerFactory.getLogger(ClassWithLogs.class);

public String getNormalizedName(Person person) {

log.info("getNormalizedName called");

log.debug("Normalizing " + person.toString());

String normalizedName =

person.getName().toUpperCase().trim();

log.debug("Normalized name is: " + normalizedName);

return normalizedName;

}

}

Eager Evaluation

Boilerplate

Page 10: Java 8 and Beyond, a Scala Story

Improvement?

public class LoggingSample implements Logging {

public String getNormalizedName(Person person) {

info("getNormalizedName called");

debug("Normalizing " + person.toString());

String normalizedName =

person.getName().toUpperCase().trim();

debug("Normalized name is: " + normalizedName);

return normalizedName;

}

}

Page 11: Java 8 and Beyond, a Scala Story

Java Interface Limitations

• No state allowed

– Need Logger instance

– Workaround: getter

– But... boilerplate :-(

• Only public methods

– Logging APIs visible!

– … as is logger()

public interface Logging {

Logger logger();

default void debug(String msg) {

if (logger().isDebugEnabled())

logger().debug(msg);

}

default void info(String msg) {

if (logger().isInfoEnabled())

logger().info(msg);

}

}

Page 12: Java 8 and Beyond, a Scala Story

And Lazy Evaluation?

• Can be implemented with a lambda:

import java.util.function.Supplier;

default void debug(Supplier<String> message) {

if (getLogger().isDebugEnabled())

getLogger().debug(message.get());

}

• But there’s boilerplate at the call site:

debug(() -> "Normalizing " + person.toString());

Page 13: Java 8 and Beyond, a Scala Story

Scala Traits

• Allow state

• Participate in

lifecycle

• Support

visibility

• Multiple

inheritance!

trait Logging {

private val logger =

LoggerFactory.getLogger(getClass)

protected def warn(msg: => String) =

if (logger.isWarnEnabled)

logger.warn(msg)

protected def debug(msg: => String) =

if (logger.isDebugEnabled)

logger.debug(msg)

}

Page 14: Java 8 and Beyond, a Scala Story

SHOWCASE #2: PATTERN MATCHING

Page 15: Java 8 and Beyond, a Scala Story

Switcheroo

• Switch statement is incredibly limited

– Only supports primitives (and strings)

– No arbitrary expressions (e.g. guards)

– No result values

• Workarounds are ugly

– Nested control structures

– Encoding enums instead of using types

Page 16: Java 8 and Beyond, a Scala Story

Pattern Matching

• Pattern matching in

Scala:

– Allows arbitrary types

– Supports guards

– Checks for

exhaustiveness

– User-extensible

– Ubiquitous

Page 17: Java 8 and Beyond, a Scala Story

ARE YOU READY FOR CODE?

Page 18: Java 8 and Beyond, a Scala Story

SHOWCASE #3: IMPLICITS

Page 19: Java 8 and Beyond, a Scala Story

Serialization in a Nutshell

• Break compound type into components

Reflection

• Iterate over components

• Dispatch by type

Dispatch• Make your

customers happy

• Save the world

• Adopt a puppy

Profit

Page 20: Java 8 and Beyond, a Scala Story

Right. So?

• Jackson uses runtime reflection

– Hard to predict

– Lossy (e.g. erasure)

• Pluggable via modules

– Easy to forget

– Test to avoid mistakes

Page 21: Java 8 and Beyond, a Scala Story

A Better Way

• Scala supports implicit parameters

– These are filled in by the compiler

– Well-defined rules for implicit search

• This lets you define type classes:

trait Serializer[T] {

def serialize(value: T): JsonValue

def deserialize(value: JsonValue): Try[T]

}

Page 22: Java 8 and Beyond, a Scala Story

Composition

• Type classes are resolved recursively

• You can encode dependencies:

– If Serializer[T] is known, you can always handle Option[T]

– Same principle applies to maps, sequences etc.

• The compiler handles wiring for you

– To an arbitrary level of nesting!

Page 23: Java 8 and Beyond, a Scala Story

How Is That Better?

• Performance

– No reflective access

– No runtime codegen

• Reliability

– Missing serializer = compile-time error

– Lossless

– No spurious tests

Page 24: Java 8 and Beyond, a Scala Story

WE’RE DONE HERE!… AND YES, WE’RE HIRING :-)

Thank you for listening

[email protected]

@tomerg

http://il.linkedin.com/in/tomergabel

Sample Code:

https://github.com/holograph/scala-vs-java8