Ich stolperte auf der Treppe und fand einen Rubin ;-)

(Ich möchte voranstellen, dass ich kein Informatiker sondern ‘nur’ Ingenieur für Bioverfahrenstechnik (FH) und Elektromechaniker bin. Anderenfalls hätte ich das folgende sicher im Studium gelernt statt durch eigene Erfahrung.)

Weiter, immer weiter!
Nachdem ich mein erstes Projekt mit VisualBasic verwirklichen konnte und 5 Jahre lang mit Perl 5 programmiert habe wollte ich eine “richtige” Programmiersprache lernen, wie sie in der Industrie weithin verwendet wird. Meine Wahl fiel auf Java bis als ich einen Artikel über Scala las und natürlich Scala zu lernen begann. Dazu war es für mich notwendig, erst einmal Grundkenntnisse in Java zu haben. Ich fuhr also zunächst fort Java zu lernen und brachte mir dann mit Hilfe von “Programming in Scala” (auch als “the stairway book” bekannt) soviel Scala bei, dass ich die Bibliothek “DecisiontableLib” (als OpenSource in meinem sourceforge-Projekt decisiontable verfügbar) fertig schreiben und testen konnte . Dann mußte ich mich etwas mit Buildsystemen (Maven, Gradle) und Versionsverwaltung jenseits von SVN (Mercurial), Swing für eine GUI und der Testautomatisierungssoftware Quicktest Professional(R) von HP befassen.

Ich stolperte auf der Treppe…
Dadurch schrieb ich drei oder 4 Monate lang kaum Scala. Als ich meine Arbeit an DecisiontableApp (Scala+Swing) fortsetzen wollte, merkte ich, das es mir schwerfiel wieder mit Scala zu coden. Irgendwie war mir der Faden gerissen.

…und fand einen Rubin
Plötzlich bekam ich Lust mir Ruby anzusehen. Ich las “the pickaxe book auf Deutsch” und “Ruby Kurz&Gut” aus dem O’Reilly Verlag und entdeckte zu meiner größten Überraschung alles wieder, was ich in Scala gelernt hatte! Bspw.:
- Traits (heißen in Ruby Module)
- Singletons
-  Codeblöcke sind Objekte
- funktionale Programmierung (Bsp.: ein Vergleich gibt in beiden Sprachen true oder false zurück)

Dazu solch eine reichhaltige Umgebung: Ausgehend von Perl 5 (2003 bis 2008) hätte ich nicht gedacht eine Skriptsprache einen Debugger und einen interaktiven Interpreter hat sowie von Hause aus ein Framework für Unititests mitbringt!

Wozu gibt es Scala?!?
Ich sah mir Ruby an und verglich es in Gedanken Scala. Was, wenn Ruby genauso leistungsfähig wie Scala ist? Seine Syntax ist (für mich) gefühlte 10x einfacher!  Beispiel: Erweiterung der Klasse Array aus der Standardbibliothek in Ruby:

class Array
    def my_sort
        self.sort
    end
end

Dieser Code erweiterte die eingebaute Klasse Array mit der Methode “my_sort” (“self.sort” ruft nur die Methode sort der Klasse Array auf damit ich damit etwas zeigen kann. Um “sort” in “my_sort umzubenennen gibt es in Ruby einen besseren Weg.) Ich brauche nur 3-4 Schlüsselwörter zu kennen: class, def, end und vielleicht self. Mit Scala sieht dieses Beispiel so aus.

Die Antwort liefert dieser Blogeintrag: Ruby- und JRubyprogramme laufen viel langsamer als Javaprogramme! Eigene Messungen bestätigten das (der Code für Ruby wurde von der angegebenen Quelle unveränder übernommen, der Code für Scala wurde aus dem Rubycode(!) selbst erstellt:
jruby 1.6.0 (ruby 1.8.7 patchlevel 330) (2011-03-15 f3b6154) (Java HotSpot(TM) Client VM 1.6.0_24) [linux-i386-java]
Time per iteration = 59.17 microseconds
Time per iteration = 59.56 microseconds
Time per iteration = 59.52 microseconds

Scala code runner version 2.8.1.final — Copyright 2002-2010, LAMP/EPFL
Time per iteration = 2901 nanoseconds.
Time per iteration = 2950 nanoseconds.
Time per iteration = 2870 nanoseconds.
(Anmerk. des Autors: Das sind weniger als 3 microseconds)

Mirah wird alles ändern
Das ist natürlich ein schönes Dilemma: Einfach mit Ruby, schnell mit Scala. Aber mir geht die Ähnlichkeit von Scala und Ruby nicht aus dem Kopf. Als ich schon über einen Ruby->Scala Compiler nachdachte (ich müsste über jede def in Ruby eine Scala-def schreiben, damit die für Scala nötige Typdeklaration in Funktionen und Methoden generiert werden kann ;-)) stolperte ich über das Projekt Mirah (Siehe wikipedia.en).

Das wäre der Hammer. Ich könnte mein Zeug fix in (beinahe-)Ruby schreiben – und es wäre trotzdem schnell wie Scala. Für Scala befürchte ich nun das Schlimmste.

(Armer Martin Odersky: Schon wieder eine Sprache, die er entworfen hat und die niemand nutzt. Der Mann kann einem echt leid tun.)

——————–Anhang————————

Wie Unittests mein Leben positiv veränderten
Ich hatte auch Ruby als nächste Sprache nach Perl in Betracht gezogen, hatte mich aber dann doch dagegen entschieden, weil man hier Variablendeklarationen nicht erzwingen kann. In Perl hatte ich 2003 noch keine Unittests gemacht sondern einen Trace ausgedruckt und diesen mit dem Soll verglichen. Das klappte recht gut, trotzdem würde ich es heute nicht mehr machen, weil: Dadurch hatte ich mir angewöhnt, umfangreiche Funktionen mit vielen Verzweigungen zu schreiben. Ohne Variablendeklaration wäre ich hier verloren! In (oder durch?) Java begann ich Unittests zu schreiben. Das veränderte meinen Stil dahingehend, dass ich nun lieber mehrere kleine Funktionen statt einer großen schreibe. Nun brauche keine Deklaration mehr: Die Tests decken alle Fehler zuverlässig auf und der Code ist überschaubar. Somit muß ich Variablen nicht mehr deklarieren.

Scalacode zum Performancetest:
Chain.scala

package com.dnene.josephus

class Chain (size: Int) {
    private var first: Person = null

   	var last: Person = null
    var current: Person = null
    for (i <- 0 until size) {
        current = new Person(i)
        if (first == null) first = current
        if (last != null) {
            last.setNext(current)
            current.setPrev(last)
        }
        last = current
    }
    first.setPrev(last)
    last.setNext(first)

    def kill(nth: Int): Person = {
        var current = first
        var shout = 1
        while(current.getNext() != current)
        {
            shout = current.shout(shout, nth)
            current = current.getNext()
        }
        first = current
        return current
    }

    def getFirst() = first
}

object Run {
    def main(args: Array[String]) = {
        val ITER = 100000
        val start = System.nanoTime()
        for (i <- 0 until ITER) {
            val chain = new Chain(40)
            chain.kill(3)
        }
        val end = System.nanoTime()
        Console.println("Time per iteration = " + ((end - start) / (ITER )) + " nanoseconds.")
    }
}

Person.scala

package com.dnene.josephus

class Person (pcount: Int) {
    var count=pcount
    private var prev: Person = null
    private var next: Person = null

    def shout(shout: Int, deadif: Int): Int = {
        if (shout < deadif) return (shout + 1)
        this.getPrev().setNext(this.getNext())
        this.getNext().setPrev(this.getPrev())
        return 1
    }

    def getCount = this.count

    def getPrev() = prev

    def setPrev (prev: Person) {
        this.prev = prev
    }

    def getNext() = next

    def setNext(next: Person) {
        this.next = next
    }
}

edit 1: Absatz “Armer Martin …” in Normalgröße umformatiert. Ich lege großen Wert darauf, das dieser Absatz nicht höhnisch oder zynisch gemeint ist. Ich habe volle Hochachtung vor der unglaublichen Arbeit, die Martin Odersky und seine Mitstreiter geleistet haben.

About these ads
Veröffentlicht in Java, JRuby, Mirah, Ruby, Scala, Scalatest. Kommentare deaktiviert
Follow

Erhalte jeden neuen Beitrag in deinen Posteingang.

%d Bloggern gefällt das: