OO-Funktionales Gipfeltreffen: Scala und Bla


Wie bringt man einem objektorientierten System Funktionen bei? Scalas Antwort darauf ist, eine Funktion als ein Objekt aufzufassen und viel syntaktischen Zucker draufzustreuen. Mehr dazu hatte ich schon in diesem Artikel geschrieben. Wie sieht es andersherum aus, wie bringt man einem funktionalen System Objekte bei? Es gab und gibt viele Versuche, aber richtig überzeugen konnte mich bisher keiner: Alle Ansätze wirkten irgendwie aufgesetzt und künstlich. Aber ich bin über eine ziemlich unbekannte Sprache gestolpert, bei der sich Objektorientierung sozusagen ganz natürlich ergibt: Bla. Mir ist wirklich schleierhaft, wie so ein elegantes und überzeugendes Konzept so wenig Beachtung finden konnte. Neu ist Bla nun wirklich nicht, es wurde 1996 von Wouter van Oortmerssen geschrieben, der nicht nur andere unkonventionelle Sprachen wie false und Aardapple, sondern auch die 3D-Engines Cube und Cube 2 a.k.a. Sauerbraten entwickelt hat.

Bla fügt dem „üblichen“ funktionalen Mix ein einziges neues Element hinzu: Eine Funktion kann ihre aktelle Umgebung explizit zurückliefern. Tatsächlich lässt sich das self von Bla mit dem this vergleichen, das eine Scala-Funktion als echtes Objekt besitzt. Man muss schon genauer hinsehen, um überhaupt einen Unterschied zu anderen funktionalen Sprachen wie Haskell, OCaml oder Erlang zu bemerken:

-- The Bla Language, 4.2.2
-- http://strlen.com/files/lang/bla/Bla_paper_letter.pdf
stack[T]() = self where
    d = []
    isEmpty = d=[]
    push(x : T) = do d := [x|d]
    pop(): T = d | [] -> raise stack_empty
                 | [h|t] -> h do d := t

Die Funktion stack definiert – wie in funktionaler Sprachen inklusive Scala üblich – ein paar lokale Funktionen, darunter auch die Funktion d, die auf eine Liste mit unseren Daten zeigt. Zurückgegeben wird allerdings nicht irgendein Wert, sondern die „Umgebung“, die sich stack() geschaffen hat.

Das lässt sich nicht ganz nach Scala übersetzten. In Scala würde man vielleicht soetwas schreiben:

class Stack[T] () {
  var d = List[T]()
  def isEmpty = d == Nil
  def push(x : T) = d = x :: d
  def pop: T = d match {
      case Nil => error("stack_empty")
      case h :: t => d = t; h
  }      
}

object Stack {
  def apply[T]() = new Stack[T]()
  
  def main(args: Array[String]) {
    val stack = Stack[Int]()
    stack.push(42)
    stack.push(4711)
    println(stack.pop)
    println(stack.isEmpty)
    println(stack.pop)
    println(stack.isEmpty)
  }
}

Stack hier als Funktion zu definieren wäre nicht besonders sinnvoll. Trotzdem ähnelt die Struktur der Klasse Stack frappierend der Funktion stack[T]() in Bla – mit dem kleinen Unterschied, dass ich am Ende der Klasse kein this hinschreiben muss – die Rückgabe der von Stack erzeugten „Umgebung“ wird stillschweigend vom Konstruktor übernommen.

Das Konzept von Bla erscheint mir einfacher als das von Scala, da es ohne „Magie“ (wie es das Liften von Methoden zu Funktionen oder die apply-Methode ist) auskommt. Das Vererbungsproblem löst Bla sehr einfach: Es gibt ein Schlüsselwort implements, wobei man in der neuen Funktion die gleichen Member bereitstellen muss wie im Original, und ein Schlüsselwort extends, mit dem man zu einer vorhandenen Umgebung einer Funktion neue Member hinzufügen kann. Ein einfaches Modulsystem sorgt für die Datenkapselung.

Der Rest der Sprache ist wie bereits erwähnt recht konventionell, wenn man vom Zuweisungsoperator absieht, der natürlich für die Implementierung veränderlicher Objekte unverzichtbar ist.

Es war für mich als Nicht-C-ler nicht ganz einfach, die Sourcen zu kompilieren, aber da es jetzt läuft, werde ich auch ein wenig damit herumspielen.

Bla ist eine interessante, zu Unrecht fast vergessene Sprache, die ihrer Zeit wohl voraus war, und ich hoffe, dass sie wenigstens Impulse bei der Entwicklung neuer Sprachen geben kann.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s