Scala Vortrag im Rahmen des Seminars „Programmiersprachen“ David Ullrich In diesem Vortrag erwartet Sie: Einführung Besonderheiten der Sprache Beispiel-Anwendung: QuickSort Zusammenfassung Einführung Der Ursprung Gründe für eine neue Sprache Zielsetzung beim Entwurf Der Ursprung Prof. Martin Odersky (Pizza, GJ) Programming Methods Laboratory - LAMP Seit 2002 in der Entwicklung Erste Veröffentlichung Januar 2004 Gründe für eine neue Sprache (nach Odersky) Zunehmende Verbreitung von Web-Services stellt einen ParadigmenWechsel dar Bedarf nach Unterstützung durch Programmiersprachen entsteht Ziele beim Entwurf Verknüpfung von funktionaler und ObjektOrientierter Programmierung Kein Flickwerk Synergie Nahtlose Zusammenarbeit mit anderen Objekt-Orientierten Sprachen Pattern-Matching als Grundlage für XML-Bearbeitung Besonderheiten der Sprache Das Typsystem Klassen und Vererbung Funktionen Framework-Integration Fortgeschrittene Konzepte Das Typsystem „Alles ist ein Objekt“ klassische Objekte aus der OOP Funktionen Werte Objekte object ObjektDemo { def main(args: Array[String]): unit = System.out.println(main.toString()); } Objekthierarchie in Scala (Auswahl) scala.Any scala.AnyVal scala.AnyRef (java.lang.Object) scala.Char scala.Int scala.Object java.lang.String Benutzerdefinierte Typumwandlung Werttypen besitzen bereits verschiedene coerce-Methoden (Byte Short Int) coerce-Methoden werden implizit aufgerufen def coerce: String = { [...] } Klassen und Vererbung Singleton-Objekte Klasseninstanzen Vererbung mixin-composition generische Klassen type-bounds Singleton-Objekte Schlüsselwort object Referenzierung über den Objektnamen main-Methode bildet Startpunkt object HelloWorld { def main(args: Array[String]): unit = System.out.println(“Hello World!“); } object HelloWorld with Application { System.out.println(“Hello World!“); } Klasseninstanzen Schlüsselwort class zur Definition Schlüsselwort new zur Instanziierung keine Konstruktoren stattdessen Parameterliste class Klassendemo(a:int) { val x = a; } Vererbung Einfachvererbung mit Schlüsselwort extends Schnittstellen-Definition über trait abstract Klassen nur Oberklassen sealed Klassen nie Oberklassen Überladen mit override Signatur bei Überladen änderbar Schnittstellendefinition Schnittstellen haben keinen Zustand Parameter deshalb nicht erlaubt enthält Methodensignaturen können Methoden implementieren können andere Schnittstellen erweitern trait TraitDemo { def abstractMethod(x: any): unit; def concreteMethod(x: any): String = x.toString(); } mixin-composition Unter geeigneten Umständen kann eine Klasse auch die nur die neuen Methoden erben Die Klasse mit den neuen Methoden heißt mixin Funktioniert nur, wenn die Oberklasse des mixins eine Oberklasse der Oberklasse der zu erweiternden Klasse ist mixin-Beispiel class Point(xc: int) { val x = xc; override def toString() = “x= “ + x; } class ColoredPoint(u: int, c: String) extends Point(u) { var color = c; override def toString() = super.toString() + “, c= “ + c; } class Point2D(xc:int, yc: int) extends Point(xc) { val y = yc; override def toString() = super.toString() + “, y= “ + y; } class ColoredPoint2D(xc: int, yc: int, c: String) extends Point2D(xc, yc) with ColoredPoint(xc, c); } generische Klassen Objekttyp wird als Parameter in eckigen Klammern übergeben Parametername kann nun wie ein Typbezeichner verwendet werden class generischesBeispiel[a](xc: a) { val x: a = xc; } [...] (args: Array[String]) [...] type-bounds können Typ-Parameter einschränken lower-type-bound: Typ-Parameter T muss Oberklasse eines anderen Typs A sein T >: A upper-type-bound: Typ-Parameter T muss eine definierte Oberklasse A haben T <: A Funktionen Parameter polymorphe Funktionen Currying anonyme Funktionen Operatoren Parameter Übergabe erfolgt in Parameterlisten Typangabe nach Typbezeichner Anzahl der Parameterlisten beliebig Funktionen selbst als Parameter möglich „Funktionen höherer Ordnung“ def fktBsp2(f: int => String, v: int): String = { f(v); def fktBsp(a: int, b: String): unit = { } [...] } Polymorphe Funktionen sind generische Methoden lassen sich mit Typ-Parameter versehen lassen sich mit type-bounds einschränken kein Bruch zwischen Klassen und Funktionen def polyBsp[T](x: T, n: Int): List[T] = { [...] } Currying Angabe mehrerer Parameterlisten erlaubt allgemeinere Methoden Aufruf übergibt Parameterlisten und liefert eine Referenz auf eine „konfigurierte“ Methode def modN(n: Int)(x: Int): Boolean = { ((x % n) == 0); } def modN(x: Int): Boolean = { ((x % 2) == 0); modN(2) } Anonyme Funktionen ermöglichen Methodendefinition ohne Bezeichner Sinnvoll bei Aufruf an einer Stelle im Code implizite Definition erfolgt durch Compiler Parameter-Rumpf-Trennung durch => (x: int, y: int) => x * y Operatoren Operatoren sind ebenfalls Objekte Genauer: eine abkürzende Schreibweise Formaler: Methoden, die einen Parameter erwarten, in einer Infix-Notation b = a + 3; b = a.+(3); Framework-Integration Nahtlose Interaktion mit der JRE oder der CLR war ein Entwicklungsziel Scala derzeit ein Wrapper für JVM und Java Compiler java.lang.* ist bereits importiert Compile-Ergebnis ist Bytecode Fortgeschrittene Konzepte Local Type Inference Pattern-Matching Regular Expression Patterns Case-Classes native XML-Unterstützung Sequence Comprehensions for (val i: int <- Iterator.region(0, 23)) { for (val i: int <- Iterator.region(0, 23); i % 2 == 0) { [...] [...] } } Beispiel-Anwendung: QuickSort Scala-Implementierung OO und funktional Funktionale Implementierung vertauscht nicht, sondern filtert def sort(a: List[int]): List[int] = { if (a.length < 2) { a } else { val pivot = a(a.length / 2); sort(a.filter(x => x < pivot)) ::: a.filter(x => x == pivot) ::: sort(a.filter(x => x > pivot)); } } QuickSort in Java Java-Code im Wesentlichen durch „Schlüsselwort-Transformation“ def swap(i: int, j: int): unit = { val t = a(i); a(i) = a(j); a(j) = t; } private static void swap(int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; } Benchmark-Ergebnisse 6 5 4 3 2 1 0 100.000 1.000.000 Java 10.000.000 Scala OO Scala Fkt 100.000.000 Zusammenfassung Einige Interessante Möglichkeiten Mainstream-Features der nahen Zukunft Gute Integration Schnell genug für den täglichen Einsatz Scala ist noch nicht fertig Abschließend ... Scala (ital. Treppe) ist vielleicht nicht DER nächste Schritt, aber ein Schritt in die richtige Richtung Vielen Dank für Ihre Aufmerksamkeit.