Neue Programmiersprache Pony zielt auf Multicore-Entwicklung

Kürzlich betrat die Programmiersprache Pony die Bühne. Wie Scala, Clojure, Go oder Rust liegt ihre Motivation in der Entwicklung skalierbarer Software auf der Basis von Mehrkernrechnern – und ihr Konzept erscheint schon mal schlüssig.

 –  8 Kommentare
Neue Programmiersprache Pony zielt auf Multicore-Entwicklung

Die Welt der Programmiersprachen wird seit einiger Zeit immer wieder aufgewirbelt. Einerseits erstrahlen seit Langem existierende Sprachen wie Erlang/OTP in neuem Licht, andererseits betreten Neulinge wie Scala, Clojure, Go oder diesen Monat auch Rust die Bühne. Die Motivation hierfür liegt in der Regel in der Entwicklung skalierbarer Software auf der Basis von Mehrkernrechnern. Die Nutzung dieser Ressourcen bei gleichzeitigem sicheren Ablauf ist in vielen bestehenden Sprachen ein komplexes Thema, dem mit den individuellen Fähigkeiten einer neuen Sprachen beigekommen werden soll. Mit Pony bewegt sich seit kurzem ein noch ganz junger Vertreter der Szene im Bereich der Version 0.1.x.

Die Open-Source-Sprache der Firma Causality rund um den deutschen Sebastian Blessing vereinigt verschiedene Konzepte zu einem interessanten und durchdachten Mix. Vor der ersten programmierten Zeile wurde laut Aussage des Teams erst mal viel Zeit in die Entwicklung eines schlüssigen Konzepts gesteckt. So basiert die Sprache auf Aktoren, die Nachrichten asynchron verarbeiten. Gleichzeitig bestehen Elemente der Objektorientierung, wobei auf die Vererbung verzichtet wird. Die Sprache ist statisch typisiert, die Variablen werden durch einen Garbage Collector bereinigt, der jeweilige Zugriff ist präzise geregelt und Zeiger sowie Speicherüberläufe existieren nicht. Eine weitere Sicherheit bietet die Tatsache, dass Exceptions immer gefangen werden.

Als Laufzeitumgebung nutzt Pony LLVM auf allen unterstützten Plattformen, derzeit OS X, Linux und Windows. Der Compiler ponyc übersetzt dabei die Quellen in ein einzelnes Binary, wobei sich externe C/C++-Bibliotheken einbinden oder Header für die Einbindung in C/C++-Programme generieren lassen. Der Start für das erste Programm erfolgt über einen Aktor für das berühmte "Hello, World!".

actor Main
new create(env: Env) =>
env.out.print("Hello, World!")

Der Aktor Main ist immer der Einstiegspunkt in ein Programm, die Konstruktoren werden mit new deklariert und create() ist der Standardkonstruktor. Der Typ Env bietet hier einen Zugriff auf STDIN, STDOUT, Argument und Umgebungsvariablen. Weitere Methoden des Aktors lassen sich über fun deklarieren, zum Beispiel

fun add(a: I32, b: I32): I32 =>
a + b

Hier ist I32 ein Integer mit 32 Bit, er existiert wie auch vorzeichenlose Integer von 8 bis 128 Bit. Dazu kommen Bool, String sowie F32 und F64 für Fließkommazahlen. Hier wird schon deutlich, dass alle Typen im Gegensatz zu den Variablen klein geschrieben werden. Rückgabe einer Funktion ist das Ergebnis des letzten Ausdrucks oder eine zwischenzeitliche Rückgabe mittels return.

Spannender für die Aktoren sind natürlich eher die Behaviors. Sie werden für die asynchronen Funktionen genutzt, lösen also den Versand einer Nachricht an den Aktor aus, die im Hintergrund verarbeitet wird. Nur ist diese nicht wie in Erlang/OTP oder in Go ein über die Mailbox oder Channel versandte Nachricht an eine Schleife im Hintergrund. Sehr elegant stellt Pony hingegen die Verarbeitung an der Position des Aufrufs dar, einleitendes Schlüsselwort ist die Abkürzung be.

actor Counter
var _count: U32

new create() =>
_count = 0

be increment() =>
_count = _count + 1

Hier ist increment() ein asynchron und atomar verarbeitetes Behavior. Es kann im Gegensatz zu Funktionen allerdings keine direkte Rückgabe liefern. Wird das gewünscht, muss ein Objekt oder ein Aktor für ein Callback als Argument übergeben werden. Im Beispiel fällt zudem die Deklaration eines Felds für den Aktor mit var auf. Dieses kann so verändert werden. Werden sie hingegen mit let deklariert, lassen sie sich nur initial setzen. Das deutet noch eine weitere Eigenschaft Ponys an: Capabilities. Sie regeln die Möglichkeiten des Zugriffs auf einen Wert mit sechs Schlüsselwörten von iso bis tag. So sind Zugriffe isoliert, unveränderlich, als Referenzen, für den aktuellen Aktor nur lesbar, für ihn schreibbar und andere nur lesbar oder als Identifikator möglich. Diese Vielfalt ist nicht immer sofort eingängig, erlaubt dafür aber eine präzise Kontrolle und geht dann flüssig von der Hand.

Die Entwicklung von Klassen erfolgt analog zu Aktoren, nur jedoch mit dem Schlüsselwort class und natürlich ohne Behaviors. Praktisch ist, dass sie auch Templates ermöglichen. Das erlaubt einerseits praktische Collection Classes wie Array, Map oder Set, andererseits aber auch leicht für eigene Zwecke einsetzbare Traits und Interfaces. Hier sind Comparable und Ordered prominente Beispiele. Abgerundet wird die Klassenentwicklung durch Operator Overloading und Abkürzungen beim Konstruktor, den Zugriff auf eine Variable mit einem Schlüssel und dem Umgang mit Standardwerten für Argumente.

Der Rest der Sprache bietet Verzweigungen, Schleifen unter anderem über Iteratoren, Pattern Matching, Exceptions, Unions, Enumerations oder komplexen Typen. Während Methoden und Behaviors mehr an Python erinnern, entsprechen die Kontrollkonstrukte eher Pascal. Insgesamt entstehen so gut lesbare und verständliche Quellen.

Es ist noch zu früh, um eine gute Vorhersage für die Sprache Pony zu machen. Das Toolset besteht derzeit nur aus dem Compiler, die Bibliotheken wachsen noch, die Dokumentation im Netz ist auch noch nicht vollständig. Doch das sei bei der aktuellen Versionsnummer gestattet. Das Konzept erscheint jedoch schlüssig, die Entwicklung geht gut von der Hand. Insofern ist Pony schon eine gute Position im Segment der Spezialisten für Multicore-Entwicklung zuzutrauen. (Frank Müller) / (ane)