0% found this document useful (0 votes)
41 views

CodeTalks Scala Vs Java8 (Scala Programming Java)

The document discusses whether the functional programming capabilities of Scala have been made redundant by Java 8. It outlines key aspects of functional programming like functions, immutable values, avoidance of side effects. It then compares how these aspects are supported in Scala versus Java 8, including libraries like Immutables, PCollections, Javaslang that enhance Java 8's support. While Java 8 with these libraries allows functional programming, the document concludes that Scala remains a more comfortable solution due to weaknesses in Java like lack of data classes, tuples, expression-based control flow and tail call optimization.

Uploaded by

Johannes Stammer
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views

CodeTalks Scala Vs Java8 (Scala Programming Java)

The document discusses whether the functional programming capabilities of Scala have been made redundant by Java 8. It outlines key aspects of functional programming like functions, immutable values, avoidance of side effects. It then compares how these aspects are supported in Scala versus Java 8, including libraries like Immutables, PCollections, Javaslang that enhance Java 8's support. While Java 8 with these libraries allows functional programming, the document concludes that Scala remains a more comfortable solution due to weaknesses in Java like lack of data classes, tuples, expression-based control flow and tail call optimization.

Uploaded by

Johannes Stammer
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

New Technology

Insert company logo

Lutz Hühnken / @lutzhuehnken

Scala: Durch Java 8 überflüssig geworden?

@lutzhuehnken 29/09/2016
Was macht funktionale
Programmierung aus?

• Funktionen
• (Unveränderliche) Werte
• Keine Seiteneffekte
Funktionen

• Code vs. Daten

scala> val sum = (x:Int, y:Int) => x + y


Type of sum is (Int, Int) => Int
Werte

• Wert vs. Identität


• kein PlOP

Integer x = new Integer(5)

String hello = „Hello“


Keine Seiteneffekte

• Ausdrücke evaluieren vs. Anweisungen ausführen


• Ziel: Referenzielle Transparenz
Funktionale Programmierung
Scala vs. Java8
Die Disziplinen
• Funktionen höherer Ordnung
• Unveränderliche Werte und Datenstrukturen
• Currying, partiell evaluierte Funktionen
• Tupel
• Pattern Matching
• Ausdrücke
• Rekursion
Die Teams

• Scala - http://www.scala-lang.org
• Vereinigt OO mit FP

• Java8 mit Verstärkung:


• Immutables - https://immutables.github.io
• PCollections - http://pcollections.org
• Javaslang - http://www.javaslang.io
• Halva - https://github.com/soabase/soabase-halva
Funktionen

Was wir nicht (mehr) wollen

List<String> getNames(List<Customer> customers) {


List<String> names = new ArrayList<String>();
for (customer : customers) {
names.add(customer.getName());
}
return names;
}
Funktionen

Scala

val names = customers.map(_.name)


Funktionen

Java 8

List<String> names =
myList.stream()
.map(c -> c.name)
.collect(Collectors.toList());
Funktionen

Javaslang

List<String> names = customers.map(c -> c.name);
Unveränderliche Werte

• Werte sind unveränderlich - nicht nur die Referenz


(final), auch das Object, auf das sie zeigt! 

Werte
• Können geteilt werden
• Haben stabilen Hashcode
• Können übertragen werden
Werte

Scala

case class Time(hours: Int = 0, minutes: Int = 0)

val t1 = Time(12,0)

val t2 = Time(hours = 12)

val t3 = t2.copy(minutes = 30)


@Immutable
public final class Time {

public final Integer hours;


public final Integer minutes;

Werte public Time(Integer hours, Integer minutes) {


this.hours = hours;
this.minutes = minutes;
}

Java 8 @Override
public boolean equals(@Nullable Object other) {
if (this == other) return true;
if (!(other instanceof Time)) return false;
Time otherTime = (Time) other;

return
hours.equals(otherTime.hours) &&
minutes.equals(otherTime.minutes);
}

@Override
public int hashCode() {
return Objects.hash(hours, minutes);
}

@Override
public String toString() {
return MoreObjects.toStringHelper("Time")
.add("hours", hours).add("minutes", minutes).toString();
}
}
Werte

Immutables

import org.immutables.value.Value;

@Value.Immutable
public abstract class Time {
public abstract Integer hours();
public abstract Integer minutes();
}
Werte

Immutables

Time t1 =
ImmutableTime.builder()
.hours(12)
.minutes(0)
.build();
Werte

Halva

@CaseClass
public interface Time {
Integer hours();
Integer minutes();
}

Time t1 = new TimeCase(12,0);


Unveränderliche Datenstrukturen

Für Aggregate (Collections) muss das gleiche gelten wie


für ihre Elemente!

Auch sie wollen wir teilen und übertragen können - kein


„PlOP“.
Datenstrukturen (Collections)
Scala

scala> val v1 = Vector(1,2,3)


v1: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> v1.updated(0,3)
res0: scala.collection.immutable.Vector[Int] = Vector(3, 2, 3)

scala> v1
res1: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)
Datenstrukturen (Collections)
PCollections

import org.pcollections.PVector;

import org.pcollections.TreePVector;


PVector<Integer> pv1 = TreePVector.from(Arrays.asList(1,2,3));


pv1.with(0,3);


System.out.println(pv1.toString()); // [1, 2, 3]



Collections

• Fokussiert auf persistente Collections


• Minimale API (plus, minus, with..)
• Keine zusätzlichen Methoden, keine Lambda-
Unterstützung
• Drop-In-Replacement (PVector implementiert
java.util.List, HashPMap impl. java.util.Map..)
Datenstrukturen (Collections)
Javaslang

import javaslang.collection.Vector;

Vector<Integer> v1 = Vector.of(1,2,3);


v1.update(0,3);

System.out.println(v1.mkString(",")); // (1,2,3)
Javaslang

• Bietet „reiche“ API (mit drop, take, permutation, map,


flatMap, filter, collect, sliding, etc., entsprechend
Scala-Collections.), inkl. Funktionen höherer
Ordnung.
• Kein Drop-In-Replacement (implementiert nicht
java.util.Collection etc.)
Currying
Scala

scala> def sum(a:Int)(b:Int) = a + b


sum: (a: Int)(b: Int)Int

scala> val sum2: Function[Int,Int] = sum(2)


sum2: Function[Int,Int] = <function1>

scala> sum2(4)
res1: Int = 6
Currying

Javaslang
Function2<Integer, Integer, Integer> sum = (a, b) -> a + b;

Function1<Integer, Integer> add2 = sum.curried().apply(2);

add2.apply(4) // 6
Tupel
Scala
scala> val java8 = ("Java", 8)
java8: (String, Int) = (Java,8)

scala> java8._1
res0: String = Java

scala> java8._2
res1: Int = 8

scala> List("a","b","c").zip(List(1,2,3))
res2: List[(String, Int)] = List((a,1), (b,2), (c,3))
Tupel
Javaslang
Tuple2<String, Integer> java8 = Tuple.of("Java", 8);

String s = java8._1; // "Java"

Integer i = java8._2; // 8

List<Tuple2<String,Integer>> zipped = List.of("a", "b", "c").zip(List.of(1,2,3));



System.out.println(zipped.mkString(", ")); // (a, 1), (b, 2), (c, 3)

Pattern Matching
Scala
val s = i match {
case 1 => "one"
case 2 => "two"
case _ => "?"
}
Pattern Matching
Javaslang

String s = Match(i).of(
Case($(1), "one"),
Case($(2), "two"),
Case($(), "?")
);
Ausdrücke

• Ausdrücke („Expressions“) vs. Befehle („Statements“).


• Statements haben kein Ergebnis und werden nur um
des Seiteneffekts wegen ausgeführt.
• Wichtige Java-Kontrollstrukturen sind Statements (if,
for, while, try…).
• In Scala ist alles ein Ausdruck.
Ausdrücke
Scala
for {
n <- 1 to 3
m <- 1 to n
} yield n * m

res0: Vector(1, 2, 4, 3, 6, 9)

scala> val b = if (3 < 4) "yes" else "no"


b: String = yes
Rekursion
Scala

def factorial(n: Int, acc: BigInt = 1): BigInt =


if (n == 0) acc else factorial(n - 1, n * acc)
Rekursion

• In Scala ok, da rechtsrekursiv (tail recursive)


• In Java - java.lang.StackOverflowError
Problemfelder in Java

• Syntax - Unterstützung für Datenklassen (kommt in


Java 10?), Tupel fehlt
• Unveränderliche Datenstrukturen (Collections) fehlen
• Zu viele Anweisungen (if, switch, for..), zu wenig
Ausdrücke
• Checked Exceptions
• Keine Tail-Call-Optimierung für rechtsrekursive
Funktionen
Fazit

• Mit der Kombination Lambdas, Javaslang und Halva


oder Immutables lässt sich brauchbar funktional
programmieren - es gibt also keine Ausrede!

• Es gibt aber noch viel zu tun! Scala bleibt fürs erste


die deutlich komfortablere Lösung.
New Technology

Insert company logo

Lutz Hühnken / @lutzhuehnken

Scala: Durch Java 8 überflüssig geworden?


Antwort: Nein.

@lutzhuehnken 29/09/2016

You might also like