Die Programmiersprache Ruby (German Edition)
folgenden beiden Methoden sind zum Beispiel erlaubt:
def sequence5(args, &b) # Argumente als Hash übergeben, gefolgt von einem Block
n, m, c = args[:n], args[:m], args[:c]
i = 0
while(i < n)
b.call(i*m + c)
i += 1
end
end
# Erwartet ein oder mehrere Argumente, gefolgt von einem Block
def max(first, *rest, &block)
max = first
rest.each {|x| max = x if x > max }
block.call(max)
max
end
Diese Methoden funktionieren gut, aber beachten Sie, dass Sie die Komplexität dieser Fälle vermeiden können, indem Sie Ihre Blöcke einfach anonym belassen und mit
yield
aufrufen.
Es ist noch wichtig, darauf hinzuweisen, dass die
yield
-Anweisung in einer mit einem
&
-Parameter definierten Methode dennoch funktioniert. Selbst wenn der Block in ein
Proc
-Objekt konvertiert und als Argument übergeben wurde, kann er noch als anonymer Block aufgerufen werden, als sei das Blockargument nicht vorhanden.
6.4.5.1 & im Methodenaufruf verwenden
Wir haben weiter oben gesehen, dass Sie
*
in einer Methodendefinition verwenden können, um festzulegen, dass mehrere Argumente in ein Array gepackt werden sollen, und dass Sie
*
in einem Methodenaufruf verwenden können, um anzugeben, dass ein Array ausgepackt werden soll, damit seine Elemente zu einzelnen Argumenten werden.
&
kann ebenfalls sowohl in Definitionen als auch in Aufrufen verwendet werden. Wir haben gerade gesehen, dass
&
in einer Methodendefinition es ermöglicht, einen gewöhnlichen Block, der mit einem Methodenaufruf verknüpft ist, innerhalb der Methode als benanntes
Proc
-Objekt zu verwenden. Wird
&
vor einem Proc-Objekt in einem Methodenaufruf verwendet, dann wird die
Proc
so behandelt, als sei sie ein gewöhnlicher Block, der auf den Methodenaufruf folgt.
Betrachten Sie den folgenden Code, der die Inhalte zweier Arrays addiert:
a, b = [1,2,3], [4,5] # Mit einigen Daten anfangen
sum = a.inject(0) {|total,x| total+x } # => 6. Summe der Elemente von a
sum = b.inject(sum) {|total,x| total+x } # => 15. Die Elemente von b hinzuaddieren
Wir haben den Iterator
inject
weiter oben in „5.3.2 Enumerable-Objekte“ beschrieben. Wenn Sie sich nicht erinnern, können Sie seine Dokumentation mit
ri Enumerable.inject
nachschlagen. Der wichtige Punkt an diesem Beispiel ist, dass die beiden Blöcke identisch sind. Anstatt den Ruby-Interpreter zweimal denselben Block parsen zu lassen, können wir eine
Proc
erstellen, die den Block darstellt, und das einzelne
Proc
-Objekt zweimal verwenden:
a, b = [1,2,3], [4,5] # Mit einigen Daten anfangen
summation = Proc.new {|total,x| total+x } # Ein Proc-Objekt zur Summenbildung
sum = a.inject(0, &summation) # => 6
sum = b.inject(sum, &summation) # => 15
Wenn Sie
&
in einem Methodenaufruf verwenden, muss es vor dem letzten Argument im Aufruf stehen. Blöcke können mit einem Methodenaufruf verknüpft werden, selbst wenn die Methode keinen Block akzeptiert und niemals
yield
verwendet. Auf dieselbe Weise kann jeder Methodenaufruf ein
&
-Argument als letztes Argument enthalten.
In einem Methodenaufruf steht
&
üblicherweise vor einem
Proc
-Objekt. Aber es ist eigentlich vor jedem beliebigen Objekt mit einer
to_proc
-Methode erlaubt. Die (im nächsten Kapitel behandelte) Klasse
Method
besitzt eine solche Methode, so dass
Method
-Objekte genau wie
Proc
-Objekte an Iteratoren übergeben werden können.
In Ruby 1.9 definiert die Klasse
Symbol
eine
to_proc
-Methode, die es ermöglicht, Symbolen ein
&
voranzustellen und sie an Iteratoren zu übergeben. Wenn ein Symbol auf diese Weise übergeben wird, dann wird es als Name einer Methode interpretiert. Das von der Methode
to_proc
zurückgegebene Proc-Objekt ruft die im ersten Argument genannte Methode auf und übergibt ihr alle übrigen Argumente. Ein gewöhnlicher Anwendungsfall ist dieser: Gegeben ist ein Array von Strings, aus denen ein neues, in Großbuchstaben konvertiertes Array erzeugt wird.
Symbol.to_proc
ermöglicht es uns, das wie folgt elegant zu erreichen:
words = ['und', 'das', 'was'] # Ein Array mit Wörtern
uppercase = words.map &:upcase # Mit String.upcase in Großbuchstaben konvertieren
upper = words.map {|w| w.upcase } # Äquivalenter Code mit einem Block
6.5 Procs und Lambdas
Blöcke sind in Ruby syntaktische Strukturen; sie sind keine Objekte und können nicht als Objekte manipuliert werden. Es ist jedoch möglich, ein Objekt zu erzeugen, das einen Block darstellt. Je nachdem, wie das Objekt erzeugt wird, wird es Proc oder Lambda genannt. Procs besitzen ein blockähnliches
Weitere Kostenlose Bücher