ruby-mine

exploring the mine

Warum Ruby 1.9.0?

von bovi am 25.12.2007 (17 Uhr)

Matz ist vorbeigekommen und er hat uns etwas mitgebracht! Einen funkelnden Rubin mit der Aufschrift 1.9.0

Nun höre ich schon die ersten Leute grummeln:

Schon wieder ein neues Release? Es gab doch gerade mal vor knapp 7 Monaten die 1.8.6, sollte diese Version nicht überings 1.9.1 heißen und 0.0.4 Versionspunkte sind ja auch nicht gerade viel. ALLES DOOF!!".

Diese Leute irren sich! Die 0.0.4 Versionspunkte haben es in sich.

ruby -v

ruby 1.9.0 (2007-12-25 revision 0) [i686-darwin9.1.0]

eine Virtuelle Maschine

YARV war seit Jahren in aller Munde. Jetzt wird sie auch bald in allen Ruby Versionen stecken. Mit der 1.9.0 gibt es das erste offizielle Prerelease, dass den Quelltext nicht mehr einfach interpretiert. Statt dessen wird eine Simplifizierung mittels Bytecode durchgeführt. Die Interpretation dieses Bytecodes bringt einiges an Performance. Und diese Performancesteigerung ist nur der Anfang. Viele moderne Tuningmaßnahmen stehen noch in den Startlöchern. Definitiv die wichtigste Änderung an diesem Release.

die mächtigste Engine für Reguläre Ausdrücke der Welt !1eins!1!

Diesen Teil von Ruby nur als die mächtigste Engine für Reguläre Ausdrücke zu bezeichnen, ist eigentlich absolut untertrieben. Wie schon mehrmals festgestellt wurde, handelt es sich bei den heutigen RegExp Bibliotheken nicht mehr nur um einfache Maschinen zur Auswertung Regulärer Ausdrücke. Ich würde Sie lieber als zweite Programmiersprache in einer Programmiersprache bezeichnen. Und wir können mit Recht behaubten, dass Ruby nun die Mächtigste dieser embedded Programmiersprachen besitzt. Neigt Eure Häupter vor Oniguruma.

Wolfgang hat diesbezüglich einige Artikel verfasst:

neue_Syntax: "für Hashelemente"

Viele Ruby Entwickler haben die fehlenden Keyword Argumente zum Anlass genommen, das Hashkonstrukt wie folgt einzusetzen:

def gib_antwort(hsh = {:frage => nil})
  #ein paar triviale KI Algorithmen...
end

puts gib_antwort :frage => 'Wie lautet der Sinn des Lebens?'

Mit der neuen Version kann man dies nun ein wenig eleganter:

puts gib_antwort frage: 'Wie lautet der Sinn des Lebens?'

Lambda -> mal anders

Sehr wenige kennen es. Und noch viel weniger Ruby Entwickler nutzen es tatsächlich. Die Rede ist von Lambda:

l = lambda{ |x,y|  x + y }
l.call 5,3 # => 8

Das Ganze sieht in Zukunft so aus:

l = ->(x,y){  x + y }
l.call 5, 3 # => 8

Die alte Syntax bleibt bestehen. Die Idee hinter "->" ist ein um 90 Grad gedrehtes Lamda. Ich selbst halte das für sehr weit hergeholt aber OK.

richtige Zeichenketten == keine Byteketten

Fange wir mal klein an:

'Ich bin eine Zeichenkette'.each {|x| puts x}
# => NoMethodError: undefined method `each' for "Ich bin eine Zeichenkette":String

:each existiert nicht mehr in der String Klasse! Schauen wir weiter:

'Ich bin eine Zeichenkette'[0]
# => "I"

Früher (<1.9) hätten wir als Rückgabewert 73 erhalten. Damit aber noch nicht genug:

'Ich bin eine Zeichenkette'.encoding
# => #<Encoding:ASCII-8BIT>

Seit dieser Version ist es möglich jede Zeichenkette nach Ihrem Encoding zu fragen. Verfügbar sind aktuell:

Encoding.list
# => [#<Encoding:ASCII-8BIT>, #<Encoding:EUC-JP>, 
#        #<Encoding:Shift_JIS>, #<Encoding:UTF-8>, 
#        #<Encoding:US-ASCII>, #<Encoding:ISO-2022-JP (dummy)>]

Die berechtigte Frage ist natürlich, wenn jede Zeichenkette ein unterschiedliches Encoding haben kann, wie wird dieses Encoding denn gesetzt? Standardmäßig ist im Moment jede Zeichenkette 8Bit ASCII kodiert. Dies kann wie folgt geändert werden:

str = 'Ich bin eine Zeichenkette'
str.encoding # => #<Encoding:ASCII-8BIT>
str.force_encoding(Encoding::UTF_8)
str.encoding # => #<Encoding:UTF-8>

Wichtig sei hier noch die Anmerkung, dass mithilfe von :force_encoding nicht das Encoding selbst geändert wird. Statt dessen wird die entsprechende Zeichenkette mit dem neuen Encoding nur anders interpretiert.

optionale Parameter 'überall'

Eine etwas kniffligere Sache ist dies hier:

def gib_mir_parameter(a, b = nil, *c, d)
    [a, b, c, d]
end

gib_mir_parameter :first, :second # => [:first, nil, [], :second]

Verstanden? Ich hatte da meine Probleme. Also noch einmal Stück für Stück:

def gib_mir_parameter(a = nil, b)
  [a, b]
end

gib_mir_parameter :first # => [nil, :first]

Wir können jetzt also einem Parameter (egal wo er sich befindet) einen Defaultwert geben. Dieser wird übersprungen, sofern nicht genug Parameter übergeben wurden.

def gib_mir_parameter(*a, b)
  [a,b]
end

gib_mir_parameter :first # => [[], :first]

Es ist nun ebenso möglich, die optionalen Parameter in einem Array am Anfang der Parameterliste aufzufangen. Dies wird natürlich nur durchgeführt, wenn auch genug Parameter vorhanden sind.

gib_mir_parameter :first, :second, :third # => [[:first, :second], :third]

Murphy hat sich dies noch einmal genauer angeschaut.

Block fragt sich: "Lokale Objektreferenzen, wo seit Ihr?"

Wir schauen einfach mal auf das folgende Codestück:

a = :draussen 
l = ->(;a){a = :drinnen}
l.call # => :drinnen
a # => :draussen

Und damit es klarer wird, noch einmal auf folgendes:

a = :draussen
l = ->{a = :drinnen}
l.call # => :drinnen
a # => :drinnen

Wird eine Objektreferenz in einem Block erneut definiert, so wird diese nur lokal in dem entsprechenden Block verändert, die Referenz außerhalb des Block wird nicht angefasst. Wird eine entsprechende Referenz nicht innerhalb des Blocks deklariert, so wird die 'externe' verwendet. Der Trick mit dem Semikolon wird verwendet, um die lokalen Referenzen zu deklarieren. Damit müssen sie nicht an den Block übergeben werden.

Stdlib und kein Ende

Es gibt ein paar Neuigkeiten an der Standard Bibliotheken Front:

Iteratoren da wo man sie nicht vermutet

Iteratoren kann man nun für später sichern:

e = 4.times
e.first # => 0
e.entries # => [0, 1, 2, 3]
e.inject {|n1, n2| n1 + n2} # => 6

Pro und Kontra

Wem die Entscheidung noch schwer fällt, sollte sich eventuell die folgende Pro/Kontra Liste von Wolfgang anschauen.

Kontra

Pro

Immer noch unsicher?

Murphy hat folgendes zum Thema zu sagen:

Warum 1.9?. Weil 1.9 > 1.8. Mehr Zeit habe ich grad nicht, da ich versuche, die letzten Rails-Tests unter 1.9 zum Laufen zu bringen.

Wer jetzt immer noch nicht sicher ist, lässt sich einfach ein bisschen Zeit. Die 2.0 kommt bestimmt bald *VaporwareAlarm*. Viel Spaß bis dahin mit Ruby (1.8|1.9).

Die Zukunft wird jetzt und in Zukunft geschrieben..

Das sind bei weitem noch nicht alle Neuerungen. Ich werde mich bemühen den Beitrag in Zukunft ein wenig auszubauen. Wenn Euch weitere wichtige Punkte einfallen, dann meldet euch einfach.


Kommentar schreiben

Name (notwendig)

Mail (wird nicht veröffentlicht)

Webseite


Kommentare

  1. Chris schrieb am 25.12.2007 (23 Uhr)

    YARV klingt nett, aber die letzte Veröffentlichung war im Juli 2006, also mehr als ein Jahr alt. Das Projekt ist ja auch gesponsert. Wird das weiterentwickelt?

  2. Carsten Werner schrieb am 26.12.2007 (00 Uhr)

    Das bisher gesehene scheint sehr vielversprechend; allein Oniguruma und die Möglichkeiten beim neuen Parser ... genial. Und endlich ist das Handling bei 2Bytigen Zeichen wesentlich sicherer und bequemer. Oder die Möglichkeit gleichnamige Variablen, bei unterschiedlichem Scope genau trennen zu können, habe ich bisher sehr vermisst. OK ... die Syntax wurde an etlichen Ecken und Kanten ein wenig frisiert, aber solange die Alte noch kompatible bleibt, erhält man eine sanfte Migration. Also vom bisher gesehenen: GANZ grosses Kompliment :-)

  3. bovi schrieb am 26.12.2007 (06 Uhr)

    @Chris: YARV wird im Rahmen von Ruby direkt weiterentwickelt. Es wurde vor knapp einem Jahr in den den Kern gemergt und seitdem ist der YARV Hauptentwickler Koichi Core Entwickler bei Ruby.

  4. Olli schrieb am 26.12.2007 (11 Uhr)

    Naja alles soweit so gut und sieht auch alles gut aus bis auf diese "optionale Parameter 'überall'" ... ich habe im Gefühl, dass das Potential hat um schwer zu findende Fehler zu produzieren. Das Problem ist einfach das die Parameterübergabe undurchsichtig und unübersichtlich wird. Ich mag mich jetzt auch irren aber naja - allein dass schon der Author des Artikels Probleme hatte die Sache zu verstehen zeigt mir das diese Technik lieber sehr sehr sparsam eingesetzt werden sollte. Was denkt ihr? Ansonsten denke ich das ich wohl noch warten werde, bis die große Masse ruby 1.9 nutzt (ja ich weiss ... bin ein bissl konservativ) :)

  5. Hanmac schrieb am 04.01.2008 (08 Uhr)

    auch ich habe probleme das mit dem optionalen Parametern zu verstehen. was hat denn die höhere Priorität? = oder * oder was?

  6. murphy schrieb am 08.01.2008 (13 Uhr)

    = wird zuerst behandelt. Es ist wirklich simpel: Da es nur einen "catch-all" gibt, wird der genau dann aufgefüllt, wenn alle anderen Parameter zugewiesen wurden. Zuerst die Pflicht-Argumente, dann die optionalen von links nach rechts, dann der Rest.