Scala (Programmiersprache)
Scala | |
---|---|
![]() | |
Basisdaten | |
Paradigmen: | objektorientiert, funktional |
Erscheinungsjahr: | Seit 2001: Interne Arbeiten am EPFL 2003: Version 1 2006: Version 2 |
Designer: | Martin Odersky |
Entwickler: | École polytechnique fédérale de Lausanne unter Leitung von Martin Odersky |
Aktuelle Version: | 2.8.0 (14. Juli 2010) |
Typisierung: | statisch typisiert |
Beeinflusst von: | Java, ML, Haskell, Smalltalk, Erlang |
Betriebssystem: | plattformunabhängig |
Lizenz: | eigene, BSD ähnlich |
http://www.scala-lang.org |
Scala ist eine funktionale und objektorientierte Programmiersprache. Sie kann auf einer JVM oder .NET VM ausgeführt werden.
Der Name leitet sich von 'scalable language' ab und bringt zum Ausdruck, dass der sehr kompakt gehaltene Sprachkern die Möglichkeit bietet, häufig verwendete Sprachelemente wie z. B. Operatoren oder zusätzliche Kontrollstrukturen in Benutzerklassen zu implementieren und dadurch den Sprachumfang zu erweitern und eigene DSLs zu erstellen.
Beispiel
object HelloWorld {
def main(args:Array[String]) {
println("Hello, world!")
}
}
Geschichte
Scala wird am Labor für Programmiermethoden an der École polytechnique fédérale de Lausanne unter der Leitung von Martin Odersky entwickelt.
Martin Odersky arbeitete unter Niklaus Wirth an Modula 2 und Oberon. Ab 1995 entwickelte er zusammen mit Philip Wadler die Sprache Pizza, die Java um Generics, Funktionszeiger und Pattern Matching erweiterte. Später konzentrierten sich Wadler und Odersky mit GJ (Generic Java) auf Generics für Java, dieses Projekt führte 2004 zur Einführung von Generics in Java. Ab 1999 arbeitete Martin Odersky an der École polytechnique fédérale de Lausanne, wo er an der Verbindung funktionaler und objektorientierter Programmierung forschte und die minimalistische Hybridsprache Funnel entwickelte. Hier begann er 2001 mit der Entwicklung von Scala, die im Gegensatz zu Funnel nicht rein akademischem Interesse dienen sollte, sondern als vollwertige Sprache für reale Anwendungen ausgelegt war. Im Frühjahr 2004 wurde Scala für die Java-Platform veröffentlicht, im Juni 2004 für .NET.
Wesentliche Neuerungen im aktuellen Release 2.8:
- Überarbeitung der Collection Library
- Überarbeitung der Array Implementierung
- named und default Argumente
- Continuations
- Erweiterungen für Actor
- Neues Objekt: package
Konzepte
Englischsprachige Zusammenfassung
- Integration mit Java
- Scala-Programme können Java-JARs ansprechen und umgekehrt. Es können also alle bestehenden Java-Librarys und -Frameworks in Scala-Projekte eingebunden und dort genutzt werden. Ähnliches gilt für die meisten Tools: Entwicklungsumgebungen wie Eclipse, NetBeans oder IntelliJ unterstützen Scala genauso wie Java.
- Objektorientierung
- Scala ist im Gegensatz zu Java eine rein objektorientierte Sprache. Jeder Wert ist ein Objekt. Das gilt auch für primitive Datentypen, ohne dass es zu Performanceeinbußen kommt, denn der vom Compiler erzeugte Bytecode verwendet primitive Datentypen.
- Interfaces werden über den Mechanismus der Traits implementiert. Traits bestehen nicht nur aus Definitionen, sie können bereits konkrete Implementierungen von Methoden enthalten. Klassen können einen oder mehrere Traits "extenden". [1] und [2]. Dabei handelt es sich nicht um Mehrfachvererbung, sondern um einen Mixin-Mechanismus.
- Über das Schlüsselwort
object
(anstelle vonclass
) wird eine Implementierung des Design Pattern Singleton bereitgestellt.
- Funktionale Sprache
- Funktionen sind "first class values". Sie können an allen Stellen verwendet werden, an denen Werte erlaubt sind, z. B. Zuweisung an eine Variable (hier ist nicht das Ergebnis der Funktionsauswertung gemeint, sondern die Funktionen selbst) oder bei der Parameterübergabe. Methoden können jederzeit in Funktionen umgewandelt werden, sind selbst aber keine "first class values".
- Funktionen höherer Ordnung [3]
- Currying: Falls die Signatur einer Methode
n
Parameterlisten enthält aber mit nur1
Parameterliste aufgerufen wird, liefert sie unter Verwendung des übergebenen Parameters eine (unbenannte) Methode mitn-1
Parameterlisten zurück. [4] - Case Classes [5] implementieren ein allgemein gehaltenes Pattern Matching [6], welches nicht zu verwechseln ist mit Regular Expressions, die ausschließlich Textmuster in Strings identifizieren.
- Closures: Funktionen greifen nicht nur auf ihre Parameter und lokalen Variablen zu, sondern auch auf Variablen ihres Kontextes (Scope), welche zum Auswertungszeitpunkt gültig sind. Dadurch werden aus open terms die namensgebenden closed terms. Falls sich bei mehrfacher Verwendung der Funktion der Wert einer Variablen des Kontextes gegenüber einem früheren Auswertungszeitpunkt ändert, kann sich auch der Rückgabewert und das Verhalten der Funktion ändern.
- Typsystem
- Scala ist statisch typisiert.
- Generische Klassen verwenden Typen, die zum Entwicklungszeitpunkt noch nicht festgelegt sind, z. B.
Map[T]
- Oberklassen können abstrakte Typen vorgeben, die von deren Unterklassen in Form konkreter Typen spezifiziert werden müssen. Gleiches gilt für Variablen (
var
undval
) sowie Methoden. - Kovarianz und Kontravarianz. Typparameter einer generischen Klasse können mit einer Annotation versehen werden, die bestimmt, wie sich Untertyprelationen von Typargumenten auf die Untertyprelation von generischen Instanziierungen der Klasse auswirken. Invarianz, Syntax:
K[T]
, bedeutet, dass überhaupt kein Zusammenhang besteht. Kovarianz, Syntax:K[+T]
, bedeutet, dass sich die Relation in gleicher Richtung fortsetzt: WennT
Untertyp vonU
ist, dann istK[T]
Untertyp vonK[U]
. Kontravarianz, Syntax:K[-T]
, bedeutet, dass die Fortsetzung in der Gegenrichtung erfolgt: WennT
Untertyp vonU
ist, dann istK[U]
Untertyp vonK[T]
. Varianzannotationen beeinflussen, an welcher Stelle innerhalb der generischen Klasse der Typparameter benutzt werden darf: Kovariante Typparameter dürfen beispielsweise nicht als Typ von Methodenargumenten verwendet werden, kontravariante nicht als Rückgabetyp. [7] - Typinferenz ist eine Eigenschaft des Compilers, welche unter Scala_(Programmiersprache)#Syntax beispielhaft dargestellt ist.
- Auswertungsstrategie
- Funktionale Ausdrücke werden in Scala strikt ausgewertet. Allerdings kann durch Annotationen die verzögerte Auswertung (Lazy-Evaluation) von einzelnen Ausdrücken spezifiziert werden. Im Gegensatz hierzu werden in Haskell die Programme standardmäßig lazy ausgewertet und es existieren Strictness Annotationen.
- XML
- Zum Sprachumfang gehören "out of the box" grundlegende XML-Operationen und -Datentypen: XML Literale, Konstruktoren, Serialisierung und Deserialisierung, XPath-ähnliche Extraktion von Elementen und Attributen, Pattern Matching
- Implicits
- Methoden können mittels es modifiers
implicit
zu sogenannten implicit methods werden. Wenn der Compiler eine Methode an einem Objekt nicht findet, sucht er im lexikalischen scope nach einer implicit method mit der er das Objekt in ein neues Objekt konvertieren kann, daß die gesuchte Methode anbietet. Mit dieser Technik lassen sich die aus C# bekannten extension methods nachbilden (das sogenannte pimp my library-Pattern) und in Grenzen sogar Vererbung. - Parameter-Listen von Methoden können ebenfalls als implicit markiert werden. Wenn die Parameterliste beim Aufruf einer Methode fehlt, aber ein als implicit markierter Wert im lexicalischen scope zu finden ist, wird er automatisch anm die Methode übergeben. Hiermit ist es möglich, die aus Haskell bekannten type classes nachzubilden.
- Methoden können mittels es modifiers
Syntax
- Die Syntax der Sprache ist an Java und ML angelehnt. Von Java wurde vor allem eine Reihe von Schlüsselworten sowie die Blocksyntax übernommen, von ML die Syntax für Typannotationen und Deklarationen.
- Im Vergleich mit Java ist der Sourcecode deutlich kompakter. In den meisten Fällen kann das Semikolon am Ende einer Zeile entfallen. Man formuliert nicht sondern
typ variable
In gleicher Weise gibt man den Typ des Rückgabewertes einer Methode an:variable: typ
f(var1: typ, var2: typ): typ
- Deklaration und Definition von Werten, Variablen und Methoden mittels der Schlüsselwörter
val
,var
unddef
, gefolgt von Typangaben.
val wert: Int = 42
var variable: Double = 3.14
def methode(parameter1: String, parameter2: Boolean): Unit
- Typinferenz: In vielen Fällen ergänzt der Compiler Typangaben. Er interpretiert als
var x = "Ein Text"
var x: String = "Ein Text"
- Als Methodenname sind u. a. Bezeichner wie + - * / erlaubt. Der Compiler interpretiert alle Operatoren als Methodenaufrufe. Das Codefragment wird übersetzt zu
1 + 2
Auf dem Objekt(1).+(2)
1
wird die Methode+
aufgerufen und dabei der Parameter2
übergeben. - Methodenaufrufe mit einem einzigen Parameter können in Infixnotation und unter Weglassung der runden Klammern erfolgen, wie im obigen Beispiel oder
1 + 2
val s = "Hello World"; s indexOf 'o'
- Parameterlose Methoden können in Postfixnotation ohne Punkt und ohne runde Klammern notiert werden (ähnlich wie in Smalltalk oder Objective-C):
val i=13; var s = i toString;
IDEs und Frameworks
Neben dem Compiler scalac
steht eine Read-Evaluate-Print-Loop (REPL) namens scala
zur Verfügung. Für die IDEs Eclipse, NetBeans und IntelliJ existieren Plugins. Das Framework Lift zur Entwicklung von Web-Applikationen sowie weitere Frameworks bauen auf Scala auf.
Siehe auch
Literatur
- Martin Odersky, Lex Spoon, Bill Venners: Programming in Scala. Computer Bookshops, 2008, ISBN 0-9815316-0-1 (englisch).
- Dean Wampler, Alex Payne: Programming Scala. O'Reilly, 2009, ISBN 978-0-596-15595-7, S. 448 (HTML-Version).
- Lothar Piepmeyer: Grundkurs funktionale Programmierung mit Scala. Hanser, 2010, ISBN 978-3-446-42092-2, S. 297.