scala: ein kurzer Überblick
DESCRIPTION
Vortrag bei der Java User Group Rostock (16. 11. 2011)TRANSCRIPT
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