Außerdem: Es wird mal wieder Zeit für einen Post auf Pelzkuh, nachdem Andreas und ich zwar doch schon einiges an Posts gesammelt haben, unser Interlocking (Autorenwechsel pro Post-Anzahl) mit 3/15 aber immer noch hundmiserabel ist...
Zum Ausprobieren installiert ist Ruby schnell - unter allen Debianartigen (Ubuntu, Mint, ...) reicht ein
apt-get install irb
und schon hat man eine interaktive Konsole, in die man nach Belieben Shellscripts einbinden kann. Natürlich kann man auch klassisch deployment-orientiert entwickeln.
So, wo fangen wir an? Am besten mit den drei Kern eigenschaften: objektorientiert (radikal konsequent, mehr noch als Java), dynamisch, aber stark typisiert. Am Beispiel:
#dynamisch typisiert
a = 5
=> 5
#stark typisiert
5 + "5"
TypeError: String can't be coerced into Fixnum
#streng objektorientiert
5.class
=> Fixnum
Was man gleich sieht: die Syntax kommt sehr reduziert daher - Befehlsendmarker fehlen und bei einer leeren Argumentliste dürfen die Klammern weggelassen werden.
Schauen wir uns ein paar Spielereien mit String an:
#Praktischer Zugriff auf Variablen für Ausgaben
a = 5
c = "Es regnet schon seit #{a} Tagen!"
=> "Es regnet schon seit 5 Tagen!"
#Reguläre Ausdrücke
t = Time.now.to_s
=> "Sat Jul 14 12:06:48 +0200 2012"
#Alternativ gibt es auch die match-Methode. Tildenoperator liefert den Index im String, wo's passt
t =~ /(..):(..):(..)/
=> 11
#Wie in vielen Shells gibt es mit $ dann die geklammerten Teilausdrücke
$1
=> "12"
Lassen wir die Spielereien. Ein Blick auf die Datenstrukturen. Hier gibt es Array, Hash und Range:
#Array
a = [1,2,5,8]
=> [1, 2, 5, 8]
a[2]
=> 5
#Hash
b = {"a" => 1, "b" => 5}
=> {"b"=>5, "a"=>1}
b["a"]
=> 1
#Add Element
b["c"] = 7
=> 7
b
=> {"c"=>7, "b"=>5, "a"=>1}
#Range
(0..8)
=> 0..8
Jetzt wird's lustig: jetzt kommen die Schleifen über den Strukturen - da weiß ich immer nicht, ob ich lachen oder weinen soll...
(0..8).collect{|num| num+num}.select{|num| if (num > 10) then num end}.each{|num| puts num}
12
14
16
=> [12, 14, 16]
Wer ist mitgekommen? Also schön, noch mal ausführlich:
#einfache each-Schleife
(0..8).each{|num| puts num}
0
1
2
3
4
5
6
7
8
=> 0..8
#collect sammelt die Ergebnisse gleich wieder in einem neuen Array auf:
(0..8).collect{|num| num+num}
=> [0, 2, 4, 6, 8, 10, 12, 14, 16]
#select wählt nur bestimmte Einträge aus
(0..8).select{|num| if(num > 5) then num end}
=> [6, 7, 8]
Wem ich verrate, wie man Dateien in Ruby öffnen kann, der merkt, wie mächtig schon nur mit regulären Ausdrücken und den drei Schleifen simple Einzeiler sein können...
file = File.open("beispiel.txt")
contents = file.read
So, noch ein paar Sätze zur Erstellung von eigenen Klassen. Zeigen wir einfach mal alles wesentliche an einem Beispiel:
class Person
#bestellt den getter und setter frei Haus!
attr_accessor :vorname, :nachname
def initialize(vorname, nachname)
@vorname = vorname
@nachname = nachname
end
#was lernen wir? Das letzte Statement ist immer der Rückgabewert!
def to_s
"Der Mensch heißt #{vorname} #{nachname}."
end
end
Und schon geht's los:
p = Person.new("Max", "Muster")
puts p
Der Mensch heißt Max Muster.
p.vorname = "Maximilian"
=> "Maximilian"
puts p
Der Mensch heißt Maximilian Muster.
Wie sagt der Schwabe: ich bin begeischtert! Das soll für heute reichen - nur noch ein paar Informationen im Überblick
- Anstelle von einzigartigen Variablen (bei Java gern als static int irgendwas) kann ich gleich mit vorangestelltem Doppelpunkt Symbole mit Objektidentität erzeugen (z.B. :erdradius)
- Methoden, die ein Boolean liefern (is..., has...) enden gerne auf "?", Methoden, die einen Seiteneffekt haben, gerne auf "!"
- Es gibt zwar keine Mehrfachvererbung, aber Mix-Ins. Überall darf also einfach Code dabei stehen, der dann entweder eingebunden oder gleich ausgeführt wird.
- Wer Objekte sortieren will, bucht einfach den Comparator zu und definiert die Vergleichsmethode:
include Comparable
attr :str
def <=>(anOther)
str.size <=> anOther.str.size
end
Ui ui ui... die Schleifen sind ja echt abenteuerlich... aber irgendwie faszinierend. Danke! sehr aufschlußreich.
AntwortenLöschenÜbrigens noch ein paar Ergänzungen/Anregungen vom Ruby-Experten, die mir Klaus heute zugeschickt hat:
AntwortenLöschen1)
(0..8).collect{|num| num+num}.select{|num| if (num > 10) then num
end}.each{|num| puts num}
# Viel zu kompliziert:
(0..8).collect{|num| num+num}.select{|num| num > 10 }.each{|num| puts num}
# und eigentlich natürlich:
(0..8).select { |n| n>5 }.each { |n| puts n }
2)
file = File.open("beispiel.txt")
contents = file.read
# Besser, um ein automatisches file.close zu haben:
# das Verlassen des Blocks schließt die Datei.
contents = File.open("beispiel.txt") { |file| file.read }
# und noch besser
contents = File.read("beispiel.txt")