Die neue Version von PHP folgt vielen neuen Funktionen, eine der auffälligeren Funktionen ist die Unterstützung für Schließungen. Können wir also in Zukunft sehr coolen Code schreiben wie die Leute, die Ruby, Javascript und andere „High-Tech-Sprachen“ schreiben?
Nun, in den meisten Fällen ist es möglich, aber es gibt immer noch einige Aspekte, die sehr beunruhigend sind.
Viele mehrere Sprachen bieten sehr elegante und schöne Methoden zum Betrieb von Arrays. Im folgenden Beispiel wird die von PHP5.3 und anderen Sprachen bereitgestellte Abschlussfunktion verwendet, um zu zeigen, wie das iterierte Array „objektiv“ betrieben wird.
Übersetzungshinweis: Der Autor des Originalartikels ist relativ inkompetent. Ich kenne die Sprache Groovy und Scala nicht, daher werde ich hier die Javascript-Implementierung hinzufügen.
Bevor ich anfange, möchte ich erklären, dass dieses Beispiel nur der Veranschaulichung dient und andere Faktoren wie die Leistung nicht berücksichtigt.
„Umsehen“
Beginnen Sie mit einem einfachen Beispiel, mit dem folgenden Array:
$nums = array(10, 20, 30, 40 ); Es müssen Elemente gefunden werden, die größer als 15 im Array sind. Dann könnten wir, ohne den Abschluss zu berücksichtigen, so schreiben:
$res = array();foreach ($nums as $n) { if ($n > 15) { $res[] = $ n; Wenn die Sprache selbst Schließungsunterstützung hat, kann sie so geschrieben werden (Groovy-Sprache)
def res = nums.findAll { it > 15 } oder Scala-Sprache
val res = verwenden nums filter (_ > 15) Übersetzungshinweis: Für Javascript 1.6 lautet es wie folgt:
var res = nums.filter(function(c){return c > 15}); Da die Schleifenoperation abstrahiert wurde Sie sehen also, dass Groovy, Scala (und Javascript) alle sehr schön sind und in einer Zeile ausgeführt werden können.
Wenn Sie PHP5.3-Abschlüsse verwenden, können Sie dies natürlich auch tun
$res = array_filter($nums, function($v) { return $v > 15; } ) ;PHP verwendet dafür mehr Zeichen als Scala, aber es ist kürzer und einfacher zu lesen als das vorherige Beispiel.
Übrigens verwendet der obige PHP-Code tatsächlich die Lambda-Analyse und ist kein echter Abschluss. Dies steht nicht im Mittelpunkt unserer aktuellen Aufmerksamkeit. Ausführliche Informationen zu PHP-Abschlüssen und Lambda-Parsing finden Sie hier.
Bisher scheint es ziemlich gut zu sein, also erhöhen wir die Schwierigkeit des Problems: Finden Sie alle Elemente größer als 15, multiplizieren Sie sie dann mit 2 plus einem bestimmten Variablenwert im Bereich und geben Sie sie dann zurück.
Groovy-Implementierung:
def x = 1def res = nums .findAll { it > 15 } .collect { it * 2 + x }Scala-Implementierung:
val x = 1val res = nums filter (_ > 15) Map (_ * 2 + x) Übersetzungsanmerkung, Javascript-Implementierung:
var i = 1;var res = nums.filter(function(c){return c > 15}). function(c){return c * 2 + i}); und PHP:
$x = 1;$res = array_map( function($v) use ($x) { return $v * 2 + $x; }, array_filter( $nums, function($v) { return $v > 15; })); In Bezug auf die Codegröße scheint sich PHP von anderen Sprachen zu unterscheiden. Abgesehen von der wörtlichen Ästhetik des Codes gibt es ein zusätzliches Problem mit dem obigen PHP-Code.
Was ist beispielsweise, wenn Sie zum Vergleich Array-Schlüssel anstelle von Werten verwenden müssen? Ja, der obige Code kann nicht ausgeführt werden. Auch syntaktisch ist der obige Code sehr schwer zu lesen.
Zurück zur Natur, Sie müssen immer noch zur altmodischen Denkweise zurückkehren, um das Problem zu lösen:
$x = 1;$res = array();foreach ($nums as $n ) { if ($n > ; 15) { $res[] = $n * 2 + $x }} Puh, das sieht wieder ganz klar aus. Aber zu diesem Zeitpunkt sind Sie möglicherweise erneut verwirrt: „Warum herumspielen? Ist das nicht nur eine Array-Operation?“
Ja, das Beste kommt noch. Jetzt ist es an der Zeit, einige der erweiterten Funktionen von PHP ins Spiel zu bringen, um dieses „langweilige Problem“ zu lösen, das anscheinend zur Selbstverletzung neigt.
ArrayObject – eine Kapselung von Arrays
PHP verfügt über eine Standardbibliothek namens SPL, die eine Klasse namens ArrayObject enthält, die die Funktion bereitstellen kann, „Klassen wie Arrays zu betreiben“, wie z. B.
$res = new ArrayObject(array(10, 20, 30, 40));foreach ($res as $v) { echo "$vn";}ArrayObject ist eine integrierte Klasse, sodass Sie sie wie andere Klassen bedienen und kapseln können .
Arr – Zuckerüberzug
Da wir nun über die Funktionen von ArrayObject und Abschlüssen verfügen, können wir mit dem Versuch beginnen, es zu kapseln:
class Arr erweitert ArrayObject { static function make($array) { return new self($array); } function map($func) { $res = new self(); ($this as $k => $v) { $res[ $k ] = $func($k, $v); } return $res; } function filter($func) { $res = new self(); func($k, $v)) { $res[$k] = $v; } } return $res; }}Okay, alles ist fertig. Der umgeschriebene PHP-Code unten kann das oben genannte Problem lösen und sieht „fast“ syntaktisch aus:
$res = Arr::make($nums) ->filter(function($k, $v) { return $v > 15; }) ->map(function($k, $v) { return $ v * 2; });Wie unterscheidet sich der obige Code von der herkömmlichen Methode? Erstens können sie rekursive und Kettenaufrufe sein, sodass weitere ähnliche Operationen hinzugefügt werden können.
Gleichzeitig können die Schlüssel und Werte des Arrays jeweils über die beiden Parameter des Rückrufs manipuliert werden – $k entspricht dem Schlüssel und $v entspricht dem Wert. Dadurch können wir Schlüsselwerte in Abschlüssen verwenden, was mit der herkömmlichen PHP-Funktion array_filter nicht möglich ist.
Ein weiterer zusätzlicher Vorteil sind konsistentere API-Aufrufe. Bei herkömmlichen PHP-Funktionsoperationen kann ihr erster Parameter ein Abschluss, ein Array oder mehrere Arrays sein ... Wie auch immer, wer weiß?
Hier ist der vollständige Quellcode der Arr-Klasse, der auch andere nützliche Funktionen enthält (ähnlich wie Reduce und Walk). Tatsächlich ähnelt ihre Implementierung dem Code.
Spiel
Diese Frage ist eigentlich schwer zu beantworten – sie hängt von vielen Faktoren ab, wie zum Beispiel dem Kontext des Codes und dem Programmierer selbst. Als ich zum ersten Mal die Abschlussimplementierung von PHP sah, fühlte ich mich tatsächlich wie in die Java-Zeit vor langer Zeit zurückversetzt, als ich anfing, anonyme innere Klassen zum Implementieren von Abschlüssen zu verwenden. Obwohl dies möglich ist, scheint es natürlich überflüssig zu sein. An PHP-Abschlüssen ist nichts auszusetzen, aber ihre Implementierung und Syntax verwirren mich.
Andere Sprachen mit Abschlussfunktionen können Abschlüsse sehr bequem aufrufen und verfügen über eine elegante Syntax. Im obigen Beispiel würde die Verwendung einer herkömmlichen Schleife in Scala auch funktionieren, aber würden Sie es so schreiben? Auf der anderen Seite sagen einige Leute, dass das obige Problem auch mit PHP-Verschlüssen gelöst werden kann, aber würden Sie es im Allgemeinen so schreiben?
Es ist sicher, dass PHP-Schließungen in manchen Situationen ein scharfer Säbel sein können (z. B. verzögerte Ausführung und Ressourcenaufrufe), aber angesichts traditioneller Iterations- und Array-Operationen sind sie etwas schwierig. Lassen Sie sich nicht entmutigen, das Wichtigste ist, zu den Grundlagen zurückzukehren und kompatiblen, sauberen Code und APIs zu schreiben.
Fazit
Wie alle später hinzugefügten Syntaxfunktionen (erinnern Sie sich an die Generics-Funktion von Java damals? Und die PHP-OOP-Funktion früherer Jahre) erfordern sie alle Zeit einbrechen und sich schließlich stabilisieren. Da PHP5.3 und sogar PHP6 in Zukunft immer beliebter werden, glaube ich, dass intelligente Programmierer in naher Zukunft nach und nach immer mehr Techniken und Funktionen entdecken werden.
Gehen Sie zurück zum Titel am Anfang des Originalartikels und vergleichen Sie
$res = Arr::make($nums) ->filter(function($k, $v) { return $v > 15; }) - >map(function($k, $v) { return $v * 2; }); und
val res = nums filter (_ > 15) map (_ * 2). Letztlich handelt es sich nur um Grammatik. Im Wesentlichen lösen sie dasselbe Problem durch unterschiedliche Ansätze. Die Anwendungseigenschaften von Programmiersprachen sind unterschiedlich, daher ist es unmöglich zu vergleichen, welche besser und welche schlechter ist.
Abschließend finden Sie hier die Codebeispiele aus diesem Artikel. Ich glaube, Sie können weitere Einblicke in die Verwendung von PHP für die funktionale Iteration finden (natürlich nicht nur diese).
Das obige ist der detaillierte Inhalt vonBeschreibung der praktischen Anwendung von PHP-Abschlussfunktionen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!