SCALA: ein kurzer Überblick

Preview:

DESCRIPTION

Vortrag bei der Java User Group Rostock (16. 11. 2011)

Citation preview

SCALA: ein kurzer ÜberblickJUGHRO-Treffen November 2011

Roland EwaldInstitut für Informatik, Universität Rostock

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 1

Disclaimer

• Ich bin ein SCALA-Anfänger

• Übergang schrittweise &punktuell

• No Silver Bullet

Image source: user whatnot, http://www.flickr.com/photos/whatnot/6853556/

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 2

Überblick

Warum Scala?

Snippets & Grundkonzepte

Beispiel: Rationale Zahlen

Praxis

Zusammenfassung

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 3

Warum

• Interessante Sprache :-)

• Nutzt Java als Plattform (JVM)

• ’Kritische Masse’ scheint erreicht (scala-Tag #130 bei stackoverflow; nochvor math, testing, java-ee oder tomcat)

• Ist nicht mehr ’bleeding edge’ (aktuell Version 2.9, entwickelt seit 2003)

• Mehr Gründe auf http://www.scala-lang.org

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 4

Motivation

• Scala = Scalable Language

• Soll mit Nutzeranforderungen wachsen

• Skript ⇐⇒ Große Anwendung

• Statisch getypt (wie Java)

• Unterstützt objektorientierte UND funktionale Programmierung

• Weniger Boilerplate (kann Codelänge um 50% – 90% reduzieren)

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 5

Material

• Gutes Buch vom Entwickler der Sprache(Martin Odersky)

• Erste Auflage frei verfügbar:http://www.artima.com/pins1ed/

• Blog-Serie Scala for Java Refugees:http://www.codecommit.com/blog/scala/

roundup-scala-for-java-refugees

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 6

Funktionale Programmierung1

1. Funktionen sind Objekte erster Klasse

2. Funktionen haben keine Seiteneffekte

val meineFunktion = (x:Int, y:Int) => x + y

println(meineFunktion(1,1))

(Ein Welt für sich, Grundidee bereits durch λ-Kalkül von Church entwickelt.Beliebte funktionale Sprachen: Scheme, Haskell, OCaml, F#)

1Aus Sicht der Scala-Entwickler :)

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 7

Maps, Operatoren & das Factory-Pattern

var capital = Map("US" -> "Washington", "France" -> "Paris")

capital += ("Japan" -> "Tokyo")

println(capital("France"))Codebeispiel aus Odersky et al., Programming in Scala, 2008

Warum leicht lesbar?

• Typinferenz

• Factory-Methode ’versteckt’

• Sinvolle Operatoren

• Vordefinierte Funktionen

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 8

Interoperabilität mit Java / Neue Typen erzeugen

{

import java.math.BigInteger

def factorial(x: BigInteger): BigInteger =

if (x == BigInteger.ZERO)

BigInteger.ONE

else

x.multiply(factorial(x.subtract(BigInteger.ONE)))

println(factorial(BigInteger.TEN))

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

def factorial(x: BigInt): BigInt =

if (x == 0) 1 else x * factorial(x - 1)

println(factorial(10))Codebeispiel aus Odersky et al., Programming in Scala, 2008

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 9

Neue Kontrollstrukturen erzeugen2

actor {

var sum = 0

loop {

receive {

case Data(bytes) => sum += hash(bytes)

case GetSum(requester) => requester ! sum

}

}

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

2Diese hier sind von Erlang geborgt :-)

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 10

Weniger Boilerplate (durch ’Properties’)

class MyClass {

private int index;

private String name;

public MyClass(int index, String name) {

this.index = index;

this.name = name;

}

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

class MyClass(index: Int, name: String)Codebeispiel aus Odersky et al., Programming in Scala, 2008

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 11

Weniger Boilerplate (durch funktionaleProgrammierung)

boolean nameHasUpperCase = false;

for (int i = 0; i < name.length(); ++i) {

if (Character.isUpperCase(name.charAt(i))) {

nameHasUpperCase = true;

break;

}

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

val nameHasUpperCase

= name.exists(_.isUpperCase)Codebeispiel aus Odersky et al., Programming in Scala, 2008

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 12

Weniger Boilerplate (durch Support für n-Tupel)3

//In James II wäre das:

import james.core.util.misc.Pair;

//...

Pair<Integer,String> pair = new

Pair<Integer,String>(99,"Luftballons");

System.out.println(pair.getFirstValue());

System.out.println(pair.getSecondValue());

var pair = (99, "Luftballons")

println(pair._1)

println(pair._2)Codebeispiel aus Odersky et al., Programming in Scala, 2008

3∀n ≤ 22

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 13

Grundideen

Funktionen...

• geben immer etwas zurück (zumindest Unit)

• können teilweise definiert werden (⇒ Currying/Closures)

• werden genauso behandelt wie Werte (⇒Werte sind konstante Funktionen)4

• können lokale Funktionen enthalten

• können echt seltsame Namen haben, z.B. +, +=, ::, /

• können unterschiedlich aufgerufen werden

4Konvention: myObject.x hat keine Seiteneffekte, myObject.x() schon

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 14

Aufruf von Funktionen

class MeineKlasse {

def verdoppeln(x: Int) = 2 * x

def <<(x: Int) = verdoppeln(x)

}

val meinObjekt = new MeineKlasse()

println(meinObjekt.verdoppeln(2))

println(meinObjekt.<<(2))

println(meinObjekt verdoppeln 2)

println(meinObjekt << 2)

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 15

Aufruf von Funktionen

def main(args: Array[String]) {

args.foreach((arg: String) => println(arg))

args.foreach(arg => println(arg))

args.foreach(println(_))

args.foreach(println)

}

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 16

Grundideen

• Mehrere public Klassen pro Datei erlaubt.

• Keine primitiven Datentypen mehr (1.toString ist OK)

• Imports haben einen Gültigkeitsbereich

• Sichtbarkeit kann sehr feingranular eingestellt werden(z.B. protected[my.package], private[this])

• Objects sind Singletons(und enthalten alle statischen Methoden, static gibt es also nicht)

• Implizite Typumwandlungen

• case classes für Pattern Matching

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 17

Was ist (fast) gleich?

• Grundlegende Organisation des Codes (Pakete + Klassen)

• Kontrollstrukturen wie for, while, if etc.(teilw. mächtiger, z.B. switch⇒ match)

• Klassenbibliothek (Collections etc.)

• Speicherverwaltung (new wird jedoch weniger benutzt, wegen CompanionObjects und FP)

• Fehlerbehandlung (Exceptions)

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 18

Jetzt mal ein konkretes Beispiel...

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 19

Rationale Zahlen

Sind Zahlen der Form n

dmit n ∈ Z, d ∈ N ("‘Brüche"’)

...bauen wir also eine Klasse:

class Rational(n: Int, d: Int)Codebeispiel aus Odersky et al., Programming in Scala, 2008

Mit verständlicher Ausgabe und Kontrolle der Eingabe:

class Rational(n: Int, d: Int) {

require(d != 0)

override def toString = n +"/"+ d

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 20

Hinzufügen der Addition5

class Rational(n: Int, d: Int) {

require(d != 0)

val numer: Int = n

val denom: Int = d

override def toString = numer +"/"+ denom

def add(that: Rational): Rational =

new Rational(

numer * that.denom + that.numer * denom,

denom * that.denom

)

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

5Geht eleganter, wird gleich noch ausgebaut...

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 21

Hilfskonstruktor für n

1

class Rational(n: Int, d: Int) {

require(d != 0)

val numer: Int = n

val denom: Int = d

def this(n: Int) = this(n, 1)

override def toString = numer +"/"+ denom

def add(that: Rational): Rational =

new Rational(

numer * that.denom + that.numer * denom,

denom * that.denom

)

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 22

GGT zur Vereinfachung des Bruchs

class Rational(n: Int, d: Int) {

private val g = gcd(n.abs, d.abs)

val numer = n / g

val denom = d / g

def add(that: Rational): Rational =

new Rational(

numer * that.denom + that.numer * denom,

denom * that.denom

)

private def gcd(a: Int, b: Int): Int =

if (b == 0) a else gcd(b, a % b)

//...

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 23

’Operatoren’

class Rational(n: Int, d: Int) {

//...

def + (that: Rational): Rational =

new Rational(

numer * that.denom + that.numer * denom,

denom * that.denom

)

def * (that: Rational): Rational =

new Rational(numer * that.numer, denom * that.denom)

def <(that: Rational) = this.num * that.denom <

this.denom * that.num

//... usw.

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 24

Unäre ’Operatoren’ und Backticks

class Rational(n: Int, d: Int) {

//...

def unary_~() = new Rational(denom, num)

def unary_-() = new Rational(-num, denom)

//Sowas hier geht auch:

def `ha<ll$>$%o !`: Int = 2

//... usw.

}

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 25

’Operatoren’ für andere Typen

class Rational(n: Int, d: Int) {

//...

def + (i: Int): Rational =

new Rational(numer + i * denom, denom)

//... usw.

}Codebeispiel aus Odersky et al., Programming in Scala, 2008

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 26

Implizite Typumwandlung

class Rational(n: Int, d: Int)//...

object TestRationals {

implicit def intToRational(x: Int) = new Rational(x)

def main(args: Array[String]) {

val oneHalf = new Rational(1, 2)

val twoThirds = new Rational(20, 30)

println(oneHalf + twoThirds)

println(oneHalf < twoThirds)

println(new Rational(3))

println(~oneHalf)

println(oneHalf * 5 - oneHalf)

println(5 * oneHalf)

}

}

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 27

Vorsicht! "‘[...]creating methods with operator names anddefining implicit conversions can help you designlibraries for which client code is concise and easy tounderstand. Scala gives you a great deal of powerto design such easy-to-use libraries, but pleasebear in mind that with power comesresponsibility. [...]Conciseness will often be a big part of thatreadability, but you can take conciseness too far. Bydesigning libraries that enable tastefullyconcise and at the same timeunderstandable client code, you can helpthose client programmers work productively."’(p. 113, Odersky et al., Programming in Scala, 2.Ausgabe)

Image source: user mostuncool, http://www.flickr.com/photos/mostuncool/102762603/

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 28

’Pimp-My-Library’ Patternimport java.io._import scala.io._

class RichFile(file: File ) {

def text = Source.fromFile( file ).mkString

def text_=( s: String ) {val out = new PrintWriter( file )try{ out.println( s ) }finally{ out.close }

}}

object RichFile {implicit def enrichFile( file: File ) = new RichFile( file )

}

//...val f = new File("/tmp/example.txt")f.text = "hello world"

Von: http://stackoverflow.com/questions/6879427/scala-write-string-to-file-in-one-statement

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 29

Praxis

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 30

Tools

• Eclipse-Integration: http://www.scala-ide.org

• Test-Frameworks: JUnit etc. (Bytecode-kompatibel)

• SCALA-Konsole

• Interessante Frameworks, z.B. LIFT (http://liftweb.net/)

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 31

Maven-Integration6

<!-- ... --><dependency>

<groupId>org.scala-lang</groupId><artifactId>scala-compiler</artifactId><version>2.9.0</version>

</dependency><dependency>

<groupId>org.scala-lang</groupId><artifactId>scala-library</artifactId><version>2.9.0</version>

</dependency> <!-- ... --><build><sourceDirectory>src/main/scala</sourceDirectory><testSourceDirectory>src/test/scala</testSourceDirectory>

<plugins><plugin><groupId>org.scala-tools</groupId><artifactId>maven-scala-plugin</artifactId>

</plugin> <!-- ... -->

6Benötigt Repository http://scala-tools.org/repo-releases

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 32

Scripting#!/bin/shexec scala "$0" "$@"!#import java.io._import scala.collection.mutable.Set

if(args.size < 2) {println("Usage: addAccess hgrc_file user1 [user2 ...]")sys.exit(0)}

val singleLines = io.Source.fromFile(args(0)).mkString.split("\n")val editedLines = singleLines.map(l => if(matches(l)) update(l) else l)val out = new PrintWriter(new File(args(0)))try{ out.println(editedLines.mkString("\n")) } finally{ out.close }

def matches(line:String) = line.matches(".*allow_(read|push).*=.*")def update(line:String) = {val splitLine = line.split("=")val elems = Set() ++ splitLine(1).split(",").map(_.trim) ++ args.toList.tailsplitLine(0).trim + " = " + elems.mkString(", ")}

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 33

Zusammenfassung

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 34

Zusammenfassung

• Scala ist JVM-kompatibel

• Scala ’wächst’ mit den Aufgaben

• Scala ist ideal, um als Java-Programmierer FP zu lernen/anzuwenden

• Scala bietet Java gegenüber viele kleine Verbesserungen, kann also auchohne FP-Ambitionen genutzt werden

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 35

Interessante Features die es nicht in den Überblickgeschafft haben

• Actors (einfache nebenläufige Programmierung)

• Traits (Interfaces mit Logik!)

• Pattern Matching

• Annotationen

• Arrays

• DSLs bauen (siehe Actors)

• Unterstützung von XML & Regex

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 36

Alternativen

Java ohne Boilerplate: http://www.eclipse.org/Xtext/xtend

’Echte’ funktionale Programmierung auf der JVM: http://clojure.org

Scala in einfach:http://confluence.jetbrains.net/display/Kotlin

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 37

Material zum Weitermachen• The busy Java developer’s guide to Scala:

http://www.ibm.com/developerworks/java/library/

j-scala01228

• Programming Scala:http://ofps.oreilly.com/titles/9780596155957/

• Scala School:http://twitter.github.com/scala_school/

• 99 Scala Problems:http://aperiodic.net/phil/scala/s-99/

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 38

Lizenzen

• Bilder von Folie #2 & #28: Creative Commons BY-NC-SA 2.0

• Alle eigenen Inhalte ebenso

Siehe: http://creativecommons.org/licenses/by-nc-sa/2.0/deed.de

16. November 2011 c© 2011 UNIVERSITÄT ROSTOCK | FAKULTÄT FÜR INFORMATIK UND ELEKTROTECHNIK 39

Recommended