Ruby ist eine Sprache mit einer Reihe von leistungsstarken Funktionen - die mächtigsten sind wohl Blocks, Procs und Lambdas. Kurz gesagt, diese Funktionen ermöglichen es Ihnen, Code an eine Methode zu übergeben und diesen Code zu einem späteren Zeitpunkt auszuführen. Trotz der regelmäßigen Verwendung dieser Funktionen können viele Entwickler die subtilen Unterschiede zwischen ihnen nicht vollständig verstehen.
Studienführer: Wenn Sie sich für einen Programmierauftrag bewerben, erhalten Sie häufig ein Quiz, das Ihr Wissen und Ihre Erfahrung in einem bestimmten Fach bestimmt. Die verschiedenen Artikel dieser Serie bieten komprimierte Lösungen für die Fragen, die Sie bei solchen Tests erwarten können.Ein Block ist ein Code, der implizit durch die Verwendung einer geschweiften Klammer an eine Methode übergeben wird, …
, oder mach… ende
Syntax. Es ist gängige Konvention …
für einzeilige Blöcke und mach… ende
für mehrzeilige Blöcke. Zum Beispiel sind die folgenden Blöcke funktional gleich:
array = [1,2,3,4] array.map! do | n | n * n end => [1, 4, 9, 16] array = [1,2,3,4] array.map! | n | n * n => [1, 4, 9, 16]
Der Zauber hinter einem Block ist der Ausbeute
Stichwort; Es verzögert die Ausführung der aufrufenden Methode, um den Block auszuwerten. Das Ergebnis des Blocks wird, falls vorhanden, durch den restlichen Code in der Methode ausgewertet. Das Ausbeute
Die Anweisung kann auch Parameter akzeptieren, die dann an den Block übergeben und dort ausgewertet werden. Zusammen binden, ein einfaches Beispiel für die Karte!
Die obige Methode wäre folgende:
Klasse Array def map! self.each_with_index do | value, index | self [index] = Ertrag (Wert) Ende Ende
Diese einfache Darstellung von Karte!
nennt das each_with_index
Methode und ersetzt das Element am angegebenen Index durch das Ergebnis des Blocks. Dies ist zwar ein triviales Beispiel für die Verwendung von Blöcken Ausbeute
die Macht. Die Verwendung von Blöcken in Ruby ist endlos und wir verwenden sie häufig in unserem Code.
Das obige Beispiel zeigt eine geringfügige Einschränkung von Blöcken: Sie sind Syntax und verfügbar. Wir müssen Blöcke jedes Mal erneut eingeben, wenn wir sie auf verschiedenen Arrays wiederverwenden. Sie können jedoch einen Block für die spätere Verwendung speichern, indem Sie das Ruby Proc-Objekt verwenden. Wir können einen Proc in einer Variablen speichern und dann explizit an jede Methode übergeben, die ein aufrufbares Objekt akzeptiert. Das Umschreiben des obigen Beispiels als Proc würde folgendermaßen aussehen:
number_squared = Proc.new | n | n * n
Lass uns unser ändern Karte!
Methode zum Annehmen und Aufrufen des Proc-Objekts:
class Array def map! (proc_object) self.each_with_index do | value, index | self [index] = proc_object.call (value) end end array = [1,2,3,4] array.map! (number_squared) => [1, 4, 9, 16]
Beachten Sie, dass wir das nicht mehr verwenden Ausbeute
Stichwort; stattdessen verwenden wir direkt die Anruf
Methode für das Proc-Objekt, wobei der Wert aus dem Array übergeben wird. Wir erhalten das gleiche Ergebnis wie zuvor, speichern jedoch unseren Block in einer Variablen, um ihn später erneut zu verwenden.
Die Lambda-Funktion ist fast identisch mit Procs, jedoch mit zwei Hauptunterschieden. Zuerst überprüft ein Lambda die Anzahl der empfangenen Argumente und gibt eine zurück ArgumentError
wenn sie nicht übereinstimmen Zum Beispiel:
l = lambda "Ich bin ein Lambda" l.call => "Ich bin ein Lambda" l.call ('arg') ArgumentError: falsche Anzahl von Argumenten (1 für 0)
Zweitens liefern Lambdas geringe Gewinne, dh wenn ein Proc bei seiner Ausführung auf eine return-Anweisung stößt, stoppt er die Methode und gibt den angegebenen Wert zurück. Lambdas hingegen geben ihren Wert an die Methode zurück und lassen sie fortfahren:
def proc_math Proc.new return 1 + 1 .call return 2 + 2 end def lambda_math lambda return 1 + 1 .call return 2 + 2 ende proc_math # => 2 lambda_math # => 4
Wie du siehst proc_math
trifft die return-Anweisung im Proc und gibt den Wert von zurück 2
. Im Gegensatz, Lambda_Math
Überspringt die return-Anweisung und wertet stattdessen 2 + 2 aus.
Eine letzte Anmerkung: Ruby 1.9 führt die neue "Stabby" -Lambda-Syntax (dargestellt durch ->) ein, die funktional identisch mit der traditionellen Lambda-Syntax ist, aber die "Stabby" -Syntax ist viel sauberer.
In diesem Studienhandbuch haben wir die wichtigsten Unterschiede zwischen Blocks, Procs und Lambdas behandelt:
Für eine eingehendere Überprüfung empfehle ich die folgenden Ressourcen: