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.

Advertisements
Veröffentlicht in Java, JRuby, Mirah, Ruby, Scala, Scalatest. Kommentare deaktiviert für Ich stolperte auf der Treppe und fand einen Rubin ;-)

How to get Apache Maven to build scala projects?

How to get Apache Maven to build scala projects?

Download the file gol3.zip from [5] (at the very end of the page) and unpack the contained pom.xml. Make it to your pom.xml by adapting it to your project. The go to [1] and copy+paste the part for surefire plugin into your pom.xml and the import and @RunWith in your scalatests.

The full story

If you google for that, you’ll most probably find [1] and [2]. But both ([2] is an refrence to [1]) failed. Of cource i copied the needed import and @RunWith in my scalatests and compiled them. The error was:

Without surefire plugin: Not tests are found

With surefire plugin:


[INFO] ————————————————————————
[ERROR] FATAL ERROR
[INFO] ————————————————————————
[INFO] scala/ScalaObject
scala.ScalaObject
[INFO] ————————————————————————
[INFO] Trace
java.lang.NoClassDefFoundError: scala/ScalaObject

This affected also others (Thanks to Kenneth McDonald for asking in [3], [4] and [5]).  The key to the solution was found by Nayan Hajratwala in the Apache Maven forum [5]: He gave us in his last answer on this thread a file named gol3.zip. It containes a pom.xml which – as it is – no tests found. But i realised that the surefire plugin was missing! So i added the tag for the surefire plugin from [2] – AND IT WORKS!!! Thanks so much!

Examples_for_working_pom_xmls

Testcases wich works with this pom.xmls:
http://decisiontable.sourceforge.net -> DecisiontableLib
http://myflipflops.sourceforge.net -> Toolbox

[1] JPZ’LOG ScalaTest in Maven

[2] Is there a Scala unit test tool that integrates well with Maven?

[3] Closer, but still problems with maven an scalatest

[4] Still problems with IDEA/maven/scala test phase

[5] Problems with Scala unit testing

PS: At the very end i decided to use Gradle for my scala builds. Although i got Maven to run and read 50% of  „Maven by example“ and „Maven complete reference“ provided by sonatype, the company behind Maven, i found Gradle easier to handle.

Veröffentlicht in Apache Maven, Scala, Scalatest, Tools. Kommentare deaktiviert für How to get Apache Maven to build scala projects?

Merkwürdiger Fehler beim Kompilieren eines Scala-Tests

Beim Kompilieren eines Tests bekam ich den Fehler

error: wrong number of arguments for method apply: (Int,Int)String in class TableBuffer

??? Die Methode, die ich in der betreffenden Zeile aufrief, hatte doch keine Argumente? Und ich hatte im Aufruf auch keine angegeben? Der Aufruf lautete:

Methode()

Hm.

Ich versuchte den Aufruf:

Methode

(also ohne Klammern). Dann kompilierte der Test.

Veröffentlicht in Scala, Scalatest. Kommentare deaktiviert für Merkwürdiger Fehler beim Kompilieren eines Scala-Tests

Datenstrukturen mit „Blanko-Typ“

Über eine Sache habe ich mir vor ein paar Wochen fast den Kopf zerbrochen:

Wie mache ich es, dass meine Datenstrukturen Daten jedes Typs aufnehmen können? So wie scala.List zum Beispiel. Eine Liste interessiert es schließlich nicht, welchen Typ die Daten in ihr haben – schließlich soll eine List Daten nur speichern aber nicht verändern.

Darauf fand ich beim Blättern im sonst so tollen „Programming in Scala“ – Buch keine Antwort. Weil ich wusste was ich suchte aber nicht wusste wie das „richtig“ hieß! Auch über Google fand ich ersteinmal nichts! OberRiesenDoppelMist! Das ist der Pferdefuß der textbasierten Suche: Wenn Du nicht weist, wie alle anderen das nennen, was Du suchst, findest Du es nie. Meine Mutter kann ein Lied davon singen.

Zum Glück fand ich durch eine plötzliche Eingebung und über das Buch „Java von Kopf bis Fuß“ heraus, dass das, was ich suchte, aber nicht benennen konnte, in Java „Generics“ hieß. Damit war der Knoten geplatzt, denn nun lieferte Google das PDF „Generics in Scala und Java / Generische und objektorientierte Programmierung“ von Christian Henkel (Fachbereich Mathematik und Informatik Philipps-Universität Marburg) [1].

Darin wird sehr verständlich erklärt wozu man Generics braucht und wie man sie einsetzt. Und auf einmal war alles ganz einfach.

Und irgendwann finde ich heraus, wie „Generics“ in „Programming in Scala“ heißen!

[1] http://www.mathematik.uni-marburg.de/~henkel/paradigmen/GenericsInScalaUndJava.pdf, 28.9.2010, 22:00 GMT+1

Veröffentlicht in Scala. Kommentare deaktiviert für Datenstrukturen mit „Blanko-Typ“

„Vorführeffekt“: Scalatest bricht ab, nachdem der Rückgabewert einer Methode von Double zu Long geändert wurde

– und der Fehler lässt sich nicht wiederholen!

Die Ausgangssituation: Eine Methode gibt Double zurück. Alle Tests laufen ohne Fehler. Verglichen wird

assert(methode == 1)

assert(methode == 4)

usw.

Danach wird der Rückgabewert zu Long geändert, in dem der letzte von der Methode berechnete Wert durch „.toLong“ von einem Double zu einem Long umgewandelt wird. (Dieser Wert ist die Potenz zweier Integer, so dass das Ergebnis niemals ein Double sein wird).

Nun bricht der Test ab. Die Meldung war sinngemäß, dass eine Methode nicht vorhanden war, welche Methode, konnte ich der Meldung nicht entnehmen. Nachdem die Änderung rückgängig gemact wurde, lief der Test wieder durch.

Die geänderte Methode ließ sich ohne Fehler testen, wenn

assert(methode == 1l)

assert(methode == 4l)

usw.

getestet wurde. Nun ja, dachte ich mir, bloggst Du das mal. Ich brauche nur noch die Fehlermeldung. Leider kann ich nun die Änderung des Tests wieder rückgängig machen, ohne den Fehler zu erhalten.

Veröffentlicht in Scala. Kommentare deaktiviert für „Vorführeffekt“: Scalatest bricht ab, nachdem der Rückgabewert einer Methode von Double zu Long geändert wurde

while durch for (x -> o until y.length) ersetzen!

Ich lese das wunderbare Buch „Programming in Scala“ von Martin Odersky, Lex Spoon und Bill Venners (artima Verlag) und stelle nebenbei Java-Code auf Scala um. Das ist etwas gewagt, aber der Scala-Code muss nicht perfekt sein.

Dadurch ist mir entgangen, dass

//Das ist Java
for (int x = 0; x < y.size; x++)

prima durch

for (x -> o until y.length)

ersetzt werden kann! Ich hatte while benutzt, weil die o.g. Möglichkeit im Buch erst auf Seite 120 steht. Übrigens ist das Buch auch als Lehrbuch beispielhaft. Ich habe lange kein Buch so gut verstanden wie dieses.

Veröffentlicht in Scala. Kommentare deaktiviert für while durch for (x -> o until y.length) ersetzen!

JEdit – Spaß mit Tabs Leerzeichen

Eigentlich hatte ich mir JEdit über Utilities -> Global Options -> Editing wie unten zu sehen eingerichtet. Mit „Soft … tabs“ = „Aus“ wollte ich vermeiden, dass Tabs in Leerzeichen umgewandelt werden.

Mit Textdateien klappte das prima, aber .scala – Dateien wurden beim Öffnen immer in diese Einstellungen zurückgesetzt (zu sehen in Utilities -> Buffer Options):

Grübel … Wieso nimmt JEdit ausgerechnet für Scala die Originaleinstellungen?

Lösung: In der Datei „~/.jedit/modes/scala.xml“ („~“ steht in Pfadangaben auf Unix-Systemen immer für Ihr Homeverzeichnis) findet sich dieser Eintrag:

PROPERTY NAME="tabSize" VALUE="2"
PROPERTY NAME="indentSize" VALUE="2"

Da sind ja die „falschen“ Einstellungen. Das Ganze geändert zu:

PROPERTY NAME="tabSize" VALUE="4"
PROPERTY NAME="indentSize" VALUE="4"

und schon sind bleiben die Einstellungen wie sie sollen:

Geht doch. Die Erweiterung für Scala speichert also eigene Einstellungen für die Feinheiten der Textdatei.

Veröffentlicht in JEdit, Scala, Tools. Kommentare deaktiviert für JEdit – Spaß mit Tabs Leerzeichen