Ruby on Rails-Studienhandbuch Blöcke, Prozesse und Lambdas

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.

Blöcke

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 Ausbeutedie Macht. Die Verwendung von Blöcken in Ruby ist endlos und wir verwenden sie häufig in unserem Code.


Procs

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.


Lambdas

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.


Fazit

In diesem Studienhandbuch haben wir die wichtigsten Unterschiede zwischen Blocks, Procs und Lambdas behandelt:

  • Blöcke sind einmalig.
  • Procs existieren als Objekte.
  • Lambdas haben strenge Argumente.

Für eine eingehendere Überprüfung empfehle ich die folgenden Ressourcen:

  • Rails Study Guides hier zu Nettuts+
  • Ruby Proc Dokumentation
  • Programmieren von Ruby 1.9
  • Metaprogrammierung von Ruby: Programmieren Sie wie die Ruby Pros