Die Programmiersprache Ruby (German Edition)
manchmal als Splat-Operator bezeichnet, obwohl es kein echter Operator ist. Wir haben es schon früher bei der Behandlung der parallelen Wertzuweisung in „4.5.5 Parallele Wertzuweisung“ verwendet.
Angenommen, wir möchten den Maximalwert in einem Array finden (und angenommen, wir wissen noch nicht, dass Ruby-Arrays eine eingebaute
max
-Methode besitzen!). Wir könnten die Elemente des Array wie folgt an die (weiter oben definierte) Methode
max
übergeben:
data = [3, 2, 1]
m = max(*data) # first = 3, rest=[2,1] => 3
Sehen Sie, was ohne das
*
geschieht:
m = max(data) # first = [3,2,1], rest=[] => [3,2,1]
In diesem Fall übergeben wir ein Array als erstes und einziges Argument, und unsere
max
-Methode gibt dieses erste Argument zurück, ohne irgendwelche Vergleiche damit anzustellen.
Das
*
kann auch mit Methoden verwendet werden, die Arrays zurückgeben, um diese Arrays zur Verwendung in einem weiteren Methodenaufruf zu entpacken. Betrachten Sie die weiter oben in diesem Kapitel definierten Methoden
polar
und
cartesian
:
# Punkt (x,y) in Polarkoordinaten und zurück in kartesische konvertieren
x,y = cartesian(*polar(x, y))
In Ruby 1.9 sind Enumeratoren Splat-fähige Objekte. Um den »größten« Buchstaben in einem String zu finden, könnten wir beispielsweise schreiben:
max(*"Hallo Welt".each_char) # => 't'
6.4.3 Parametern Argumente zuweisen
Wenn eine Methodendefinition Parameter mit Standardwerten oder mit dem Präfix
*
enthält, wird die Zuordnung der Argumentwerte zu den Parametern während des Methodenaufrufs etwas kompliziert.
In Ruby 1.8 ist die Position des Spezialparameters beschränkt, so dass die Argumentwerte den Parametern von links nach rechts zugewiesen werden. Die ersten Argumente werden den normalen Parametern zugewiesen. Wenn Argumente übrig bleiben, werden sie den Parametern zugewiesen, die Standardwerte haben. Und wenn es dann noch weitere Argumente gibt, werden sie dem Array-Argument zugewiesen.
Ruby 1.9 muss bezüglich der Art und Weise, wie die Argumente den Parametern zugewiesen werden, klüger sein, weil die Reihenfolge der Parameter nicht mehr vorgegeben ist. Angenommen, wir haben eine Methode, die mit
n
normalen Parametern,
s
Parametern mit Standardwerten und einem Array-Parameter, das mit dem Präfix
*
deklariert wurde. Nehmen wir nun an, wir rufen diese Methode mit
a
Argumenten auf.
Wenn
a
kleiner als
n
ist, wird ein
ArgumentError
ausgelöst; wir haben nicht die benötigte Mindestanzahl von Argumenten bereitgestellt.
Wenn
a
größer oder gleich
n
und kleiner oder gleich
n+s
ist, werden den am weitesten links stehenden
a-n
Parametern mit Standardwerten Argumente zugewiesen. Den restlichen (rechts stehenden)
n+s-a
Parametern mit Standardwerten werden keine Argumente zugewiesen, und sie verwenden einfach ihre Standardwerte.
Wenn
a
größer als
n+s
ist, werden dem Array-Parameter, vor dessen Namen das Präfix
*
steht,
a-n-s
Argumente zugewiesen; andernfalls bleibt er leer.
Nachdem diese Berechnungen durchgeführt wurden, werden die Argumente den Parametern von links nach rechts zugeordnet, wobei jeder Parameter die passende Anzahl von Argumenten erhält.
6.4.4 Hashes für benannte Argumente
Wenn eine Methode mehr als zwei oder drei Argumente benötigt, kann es für den Programmierer, der die Methode aufruft, schwierig sein, sich die richtige Reihenfolge dieser Argumente zu merken. Manche Sprachen erlauben es Ihnen, Methodenaufrufe zu schreiben, die explizit einen Parameternamen für jedes übergebene Argument angeben. Ruby unterstützt diese Methodenaufrufsyntax nicht, aber Sie können etwas Ähnliches erreichen, indem Sie eine Methode schreiben, die einen Hash als ihr Argument oder als eines ihrer Argumente erwartet:
# Diese Methode gibt ein Array a mit n Zahlen zurück. Für jeden
# Index i, 0 <= i < n, ist der Wert des Elements a[i] is m*i+c.
# Die Argumente n, m und c werden als Schlüssel in einem Hash über-
# geben, so dass es nicht nötig ist, sich ihre Reihenfolge zu merken.
def sequence(args)
# Argumente aus dem Hash extrahieren.
# Beachten Sie den Einsatz des Operators ||, um die Standardwerte
# anzugeben, die verwendet werden, wenn der Hash einen
# gewünschten Schlüssel nicht definiert.
n = args[:n] || 0
m = args[:m] || 1
c = args[:c] || 0
a = [] # Mit einem leeren Array beginnen
n.times {|i| a << m*i+c } # Den Wert jedes Array-Elements berechnen
a # Das Array zurückgeben
end
Sie könnten diese Methode mit einem Hash-Literal-Argument wie diesem
Weitere Kostenlose Bücher