Dieser Artikel wurde von Yaphi Berhanu, Vildan Softic, Jani Hartikainen und Dan Prince überprüft. Vielen Dank an alle SitePoint -Peer -Rezensenten, die SitePoint -Inhalte für den Besten erhalten haben!
Eines der Charms von JavaScript sind seine funktionalen Programmiermerkmale. Von Anfang an waren Funktionen erstklassige Bürger in der JavaScript-Welt. Dies ermöglicht es, elegante und ausdrucksstarke Code zu schreiben, der auf vielfältige Weise leicht zusammengestellt werden kann. Die Fähigkeit, funktionale Programmierung allein durchzuführen, kann jedoch die funktionale Programmierung nicht automatisch implementieren. Ramda.js ist eine sehr beliebte Bibliothek (mit über 4K -Sternen auf GitHub), mit der wir uns helfen können, mit JavaScript für funktionale Programmierung zu beginnen.
Schlüsselpunkte
R.map
, R.prop
und R.curry
, um den Betrieb von Datenstrukturen zu vereinfachen und die Lesbarkeit und Wartbarkeit des Codes zu verbessern. Anfänger
Um das Beste aus Ramda.js zu nutzen, sollten wir mit seinen Vorteilen vertraut sein, indem wir ein kleines Node.js -Projekt erstellen. Wir können es einfach über den Node Package Manager (NPM) installieren.
npm install ramda
Normalerweise importieren wir einfach die Funktionalität der Bibliothek in den Namespace R. Auf diese Weise haben alle Anrufe bei der Ramda -Methode das R. Präfix.
var R = require('ramda');
Natürlich kann uns nichts davon abhalten, Ramda.js im Front-End-Code zu verwenden. Im Browser müssen wir nur den richtigen Pfad zur Bibliothekskopie einbeziehen. Dies kann so einfach sein wie der folgende HTML -Code -Snippet.
<🎜>
ramda.js verwendet keine DOM- oder node.js-spezifischen Funktionen. Es handelt sich nur um eine Sprachbibliothek/-erweiterung und baut auf den Strukturen und Algorithmen auf, die bereits von der JavaScript -Laufzeit ausgesetzt sind (wie in ECMascript 5 standardisiert). Bereit, eingehende Forschung durchzuführen? Schauen wir uns die praktische Anwendung einiger Funktionen an!
Konzept
Das wichtigste Konzept in der funktionalen Programmierung ist das Konzept der reinen Funktionen. Reine Funktionen sind idempotent und ändern keinen Zustand. Aus mathematischer Sicht ist dies sinnvoll, da Funktionen wie Sünde (x) sehr natürlich erscheinen und nicht von einem externen Zustand abhängen. Zusätzlich zu reinen Funktionen möchten wir auch Einzelparameterfunktionen haben. Sie sind die primitivsten. Eine Null-Parameter-Funktion bedeutet normalerweise, dass der externe Zustand geändert wird, sodass es keine reine Funktion ist. In Sprachen wie JavaScript haben wir normalerweise Funktionen mit mehreren Parametern.
Die Fähigkeit, Funktionen höherer Ordnung (d. H. Funktionen zu haben, die Funktionen als Eingabe- und Abgussfunktionen als Ausgabe annehmen können), kombiniert mit Verschlüssen (erfassen lokale Variablen), bietet uns einen guten Weg: Currying. Currying ist ein Prozess, bei dem eine Funktion mit mehreren (unter der Annahme n) Parameter in eine Funktion mit einem einzigen Parameter konvertiert wird, der eine andere Funktion mit einem einzelnen Parameter zurückgibt. Dies wird fortgesetzt, bis alle erforderlichen Parameter gesammelt werden. Angenommen, wir möchten die Funktion "Ramda.js Helfer" verwenden, um einen einzelnen Parameterwrapper zu schreiben, der testet, ob seine Parameter Zeichenfolgen sind. Der folgende Code erledigt den Job.
npm install ramda
Dies kann mit dem Currying leichter erfolgen. Da R.IS Teil von Ramda.js ist, gibt die Bibliothek eine Curry -Funktion automatisch zurück:
var R = require('ramda');
Dies ist ausdrucksstärker. Da wir R.IS mit einem einzigen Argument angerufen haben, haben wir eine Funktion. Im zweiten Anruf (denken Sie daran, der ursprüngliche Funktionsaufruf benötigt zwei Parameter), erhalten wir das Ergebnis. Aber was ist, wenn wir Ramda.js Helper -Funktionen am Anfang nicht benutzt haben? Nehmen wir an, wir haben die folgende Funktion irgendwo im Code definiert:
<🎜>
Dies ist ein komplettes Polynom zweiter Ordnung. Es verfügt über vier Parameter, die alle möglichen Werte ermöglichen. Aber normalerweise wollen wir nur x für einen festen Satz von Parametern A, B und c ändern. Lassen Sie uns sehen, wie Sie es mit Ramda.js konvertieren:
function isString (test) { return R.is(String, test); } var result = isString('foo'); //=> true
In ähnlicher Weise können wir einfach die Parameterbewertung verwenden, um Alias für eine bestimmte Teilmenge zu erstellen. Zum Beispiel kann die Gleichung x - 1 erhalten werden durch:
var isString = R.is(String); var result = isString('foo'); //=> true
In dem Fall, dass die Anzahl der Parameter nicht durch die Parameter unserer Funktion angegeben ist, müssen wir Curryn verwenden und explizit die Anzahl der Parameter angeben. Currying ist das Herzstück von Ramda.js, aber die Bibliothek scheint ohne mehr nicht so interessant zu sein. Ein weiteres wichtiges Konzept in der funktionalen Programmierung ist die Invarianz.
Der einfachste Weg, um zu verhindern, dass eine Funktion ihren Zustand ändert, besteht darin, nur eine Datenstruktur zu verwenden, die nicht geändert werden kann. Für einfache Objekte benötigen wir einen schreibgeschützten Accessor, zum Beispiel:
ist nicht erlaubt. Zusätzlich zur Deklaration von schreibgeschützten Eigenschaften können wir sie auch in Gettter-Funktionen umwandeln:var quadratic = (a, b, c, x) => x * x * a + x * b + c; quadratic(1, 0, 0, 2); //=> 4 quadratic(1, 0, 0)(2); //=> TypeError: quadratic(..) is not a function
Dies ist jetzt viel besser, das Objekt kann jedoch immer noch geändert werden. Dies bedeutet, dass jemand eine benutzerdefinierte Definition der GETX -Funktion hinzufügen kann, zum Beispiel:
var quadratic = R.curry((a, b, c, x) => x * x * a + x * b + c); quadratic(1, 0, 0, 2); //=> 4 quadratic(1, 0, 0)(2); //=> 4
npm install ramda
Der beste Weg, um Invarianz zu erreichen, besteht darin, Objekt zu verwenden. Freeze. In Kombination mit dem CONT -Schlüsselwort können wir eine invariante Variable einführen, die nicht geändert werden kann.
var R = require('ramda');
Ein weiteres Beispiel beinhaltet Listen. Das Hinzufügen eines Elements zu einer unveränderlichen Liste erfordert das Kopieren der ursprünglichen Liste und das Hinzufügen eines neuen Elements zum Ende. Natürlich können wir auch das Invarianzwissen des ursprünglichen Objekts nutzen, um die Implementierung zu optimieren. Auf diese Weise können wir die Kopie durch eine einfache Referenz ersetzen. Dies könnte sich im Wesentlichen in eine verlinkte Liste verwandeln. Wir sollten erkennen, dass Standard -JavaScript -Arrays veränderlich sind und daher kopiert werden müssen, um die Korrektheit zu gewährleisten. Methoden wie append () arbeiten an JavaScript -Arrays und geben solche Arrays zurück. Die Operation ist idempotent;
<🎜>
Es gibt auch eine Entfernungsmethode, die das angegebene Array zurückgibt, aber nicht den angegebenen Eintrag enthält. Es funktioniert wie folgt:
function isString (test) { return R.is(String, test); } var result = isString('foo'); //=> true
Da es eine flexible Anzahl von Parametern enthält, benötigen wir die zuvor erwähnte Curryn -Funktion, um die Curryisierung anzuwenden. Es gibt auch einige nützliche allgemeine Helferfunktionen.
Praktische Methoden
Das wichtigste Konzept aller Helferfunktionen ist, dass die Parameter zur Erleichterung der Currying angeordnet sind. Je häufiger der Parameter geändert wird, desto weniger wahrscheinlich ist er vor den anderen Parametern.
Natürlich finden Sie gemeinsame Funktionen in Ramda.js wie Summe und Bereich:
var isString = R.is(String); var result = isString('foo'); //=> true
für range () helferfunktionen können wir einen Wrapper mit Curry erstellen:
var quadratic = (a, b, c, x) => x * x * a + x * b + c; quadratic(1, 0, 0, 2); //=> 4 quadratic(1, 0, 0)(2); //=> TypeError: quadratic(..) is not a function
Was ist, wenn wir es mit einem festen (exklusiven) Maximum einwickeln möchten? Ramda.js erfüllt unsere Anforderungen, indem sie spezielle Parameter verwenden, die durch r .__:
dargestellt werdenvar quadratic = R.curry((a, b, c, x) => x * x * a + x * b + c); quadratic(1, 0, 0, 2); //=> 4 quadratic(1, 0, 0)(2); //=> 4
Außerdem versucht Ramda.js, eine "bessere" Lösung zu verwenden, um Alternativen zu JavaScript -Kernfunktionen wie Array.Prototype.map bereitzustellen. Die "bessere" Lösung hat unterschiedliche Parameterreihenfolge und das Currying aus dem Box. Für die Kartenfunktion, wie unten gezeigt:
var xOffset = quadratic(0, 1, -1); xOffset(0); //=> -1 xOffset(1); //=> 0
Ein weiteres nützliches Nutzen ist die Prop -Funktion, die versucht, den Wert der angegebenen Eigenschaft zu erhalten. Wenn die gegebene Eigenschaft nicht vorhanden ist, wird undefiniert zurückgegeben. Dies mag eindeutig sein, wenn der Wert tatsächlich undefiniert ist, aber in der Praxis kümmern wir uns selten darum.
var position = { x: 5, y: 9 }; position.x = 10; // works!
Wenn die zuvor eingeführte Methode Sie nicht davon überzeugt, dass Ramda.js etwas Nützliches liefern, kann die nächste Methode interessanter sein. Dieses Mal werden wir kein bestimmtes Beispiel diskutieren, sondern sich beliebige ausgewählte Szenarien ansehen. Angenommen, wir haben zwei Listen und möchten sie verbinden. Die Verwendung der ZIP -Funktion ist eigentlich sehr einfach. Die üblichen Ergebnisse (Arrays von Elementen, die selbst doppelt bewertete Arrays sind) sind jedoch möglicherweise nicht das Ergebnis, das wir wollen. Hier kommt die Reißverschlussfunktion ins Spiel. Es ordnet die Werte unter Verwendung willkürlicher Funktionen auf einen einzelnen Wert ab.
var position = (function (x, y) { return { getX: () => { return x; }, getY: () => { return y; } }; })(5, 9); position.getX() = 10; // does not work!
In ähnlicher Weise können wir das DOT -Produkt in den Vektor einführen:
npm install ramda
Wir komprimieren zwei Arrays durch Multiplikation (Generierung [1, 4, 9]) und übergeben das Ergebnis an die Summenfunktion. In jedem Fall ist die Verwendung von aufzählbaren Objekten ein wichtiges Thema. Es ist keine Überraschung, dass Ramda.js viele nützliche Helferfunktionen bietet. Wir haben R.MAP eingeführt, um Funktionen auf jedes Element anzuwenden. In ähnlicher Weise gibt es einige Helferfunktionen, die die Anzahl der Elemente verringern. Ein einzelner Wert kann durch die allgemeinste Filterfunktion (generiert ein anderes Array) oder durch die Reduzierung der Funktion.
Es gibt einige nützliche Helferfunktionen für den Betrieb des Arrays. Zum Beispiel können wir mit der Kette Arrays leicht zusammenführen. Angenommen, wir haben eine Funktion Primefactorisierung, die Zahlen als Eingabe verwendet und ein Array mit Primfaktoren als Ausgabe angibt. Wir können das Ergebnis der Anwendung der Funktion mit einer Reihe von Zahlen wie folgt kombinieren:
var R = require('ramda');
Bisher lief alles gut. Die größte Frage ist jetzt: Welche Vorteile sind die Vorteile unserer täglichen Arbeit mit diesen Konzepten, die von Ramda.js eingeführt wurden? Nehmen wir an, wir haben den folgenden (bereits sehr gut aussehenden) Code -Snippet.
<🎜>
Wie kann man Ramda.js verwenden, um es lesbarer zu machen? Nun, die erste Zeile ist gut genug. Die zweite Zeile ist bereits sehr verwirrend. Was wir wirklich wollen, ist die Posteigenschaft der bereitgestellten Parameter zu extrahieren. Schließlich haben wir eine etwas verwirrende dritte Linie. Hier versuchen wir, alle Beiträge zu iterieren (bereitgestellt durch Parameter). Wiederum ist sein einziger Zweck, bestimmte Eigenschaften zu extrahieren. Wie wäre es mit der folgenden Lösung?
function isString (test) { return R.is(String, test); } var result = isString('foo'); //=> true
Dies ist wahrscheinlich die beste Lesbarkeitslösung dank RAMDA.JS-fähiger funktionaler Programmierung. Wir sollten jedoch beachten, dass die in ECMascript 6 eingeführte "Fat-Pfeil" -Syntax ebenfalls zu sehr prägnantem und leicht zu lesendem Code führt:
var isString = R.is(String); var result = isString('foo'); //=> true
Dies ist fast so einfach zu lesen, ohne Ramda.js -Wissen. Darüber hinaus reduzieren wir die Anzahl der Abstraktionen - dies wird nur Leistung und Wartbarkeit zugute kommen.
Linsen
Schließlich sollten wir auch nützliche Objekthelferfunktionen diskutieren. Es ist hier erwähnenswert, dass die Objektivfunktion ist. Ein Objektiv ist ein spezielles Objekt, das zusammen mit einem Objekt oder Array an bestimmte Ramda.js -Funktionen übergeben werden kann. Es ermöglicht diese Funktionen, Daten aus bestimmten Eigenschaften oder Indizes eines Objekts bzw. Array abzurufen oder umzuwandeln. Angenommen, wir haben ein Objekt mit zwei Schlüssel X und Y - genau wie das Invarianzbeispiel zu Beginn des Artikels. Anstatt das Objekt in ein anderes Objekt mit Getter- und Setter -Methoden zu wickeln, können wir ein Objektiv erstellen, um sich auf die interessierenden Eigenschaften zu konzentrieren. Um ein Objektiv zu erstellen, das auf das X -Attribut eines Objekts zugreift, können wir Folgendes tun:
var quadratic = (a, b, c, x) => x * x * a + x * b + c; quadratic(1, 0, 0, 2); //=> 4 quadratic(1, 0, 0)(2); //=> TypeError: quadratic(..) is not a function
Obwohl Prop ein Standardfaser ist (dies wurde eingeführt) ist Assoc eine Setterfunktion (drei Wertsyntax: Schlüssel, Wert, Objekt). Jetzt können wir die Funktionen in Ramda.js verwenden, um auf die von dieser Linse definierten Eigenschaften zuzugreifen.
npm install ramda
Beachten Sie, dass diese Operation das angegebene Positionsobjekt nicht berührt (unabhängig davon, ob wir sie einfrieren oder nicht). Es sollte beachtet werden, dass Set nur ein Sonderfall von Over ist, der ähnlich ist, aber Funktionen anstelle von willkürlichen Werten nimmt. Die Funktion wird dann verwendet, um den Wert umzuwandeln. Zum Beispiel multipliziert der folgende Anruf die X -Koordinate mit 3:
var R = require('ramda');
ramda.js, lodash oder andere?
Eine vernünftige Frage ist natürlich, warum Ramda.js ausgewählt wird - warum verwenden wir nicht Lodash oder so? Natürlich könnte man argumentieren, dass Ramda.js aktualisiert ist, also muss es besser sein, aber das ist weit von der Wahrheit entfernt. Die Wahrheit ist, dass Ramda.js unter Berücksichtigung funktionaler Prinzipien erstellt wird - mit einem neuen Ansatz zur Platzierung und Auswahl von Parametern (für JavaScript -Bibliotheken). Beispielsweise übergibt der Listen -Iterator in Ramda.js standardmäßig nur Elemente, nicht Listen. Andererseits besteht der Standard für andere Bibliotheken (z. B. Lodash) darin, Elemente und Indizes an Rückruffunktionen zu übergeben. Dies scheint ein kleines Problem zu sein, aber es hindert Sie daran, bequeme integrierte Funktionen wie ParseInt () (das ein optionales zweites Argument erfordert) bei der Verwendung von Ramda.js zu verwenden, dies funktioniert einwandfrei. Letztendlich hängt das, was Sie wählen, von den spezifischen Anforderungen oder der Erfahrung und/oder dem Wissen des Teams ab, aber es gibt sicherlich einige gute Gründe, Ramda.js die Aufmerksamkeit zu erhalten, die es verdient.
Weitere Lesen
Schlussfolgerung
funktionelle Programmierung sollte nicht als Allheilmittel angesehen werden. Stattdessen sollte es als natürliche Ergänzung zu unserer vorhandenen Toolbox angesehen werden, die uns eine größere Kompositionsfähigkeit, größere Flexibilität und eine größere Fehlertoleranz/Rotabilität bietet. Moderne JavaScript -Bibliotheken haben versucht, einige funktionale Konzepte zu nutzen. Ramda.js ist ein leistungsstarkes Tool, das Ihre eigene funktionale Versorgungsbibliothek erweitert. Was halten Sie von funktionaler Programmierung? In welchen Aspekten funktioniert es Ihrer Meinung nach gut? Bitte lassen Sie es mich in den Kommentaren wissen!
FAQs (FAQs) zur funktionalen Programmierung mit Ramda
ramda ist eine praktische funktionale Bibliothek für JavaScript -Programmierer. Es ist für den funktionalen Programmierstil ausgelegt, wodurch funktionale Pipelines erstellt werden können und die Benutzerdaten niemals ändert. Der Hauptvorteil bei der Verwendung von Ramda besteht darin, dass die Invarianz- und Nebenwirkung-freie Funktionen betont. Dies bedeutet, dass die Funktion ihre Eingabedaten nicht ändert und Ihren Code erleichtert und testen kann. Die Funktionen von RAMDA werden automatisch Curry -Currys, sodass Sie problemlos neue Funktionen aus alten Funktionen erstellen können, ohne sich in einer Reihe von Klammern oder Callback -Hölle zu verlieren.
Im Gegensatz zu anderen JavaScript -Bibliotheken wird RAMDA so konzipiert, dass sie die funktionale Programmierung unterstützt und die Daten nicht ändert. Es bietet eine Reihe praktischer Funktionen, die standardmäßig Curry sind, was bedeutet, dass sie zusammen verwendet werden sollen, um neue Funktionen zu erstellen. Dies unterscheidet sich sehr von Bibliotheken wie Unscore oder Lodash, die standardmäßig nicht curryartig sind und in der Regel zusätzlichen Code schreiben, um die gleichen Ergebnisse zu erzielen. Die API von Ramda ist auch konsistenter und einfacher zu bedienen, wobei der Schwerpunkt auf Einfachheit und Lesbarkeit liegt.
Ja, RAMDA kann mit anderen JavaScript -Bibliotheken und -Refrigationen verwendet werden. Es handelt sich um eine eigenständige Bibliothek, die nicht von anderen Bibliotheken oder Frameworks abhängt und JavaScript -Objektprototypen nicht ändert. Dies ist sicher, mit anderen Bibliotheken oder Frameworks zusammenzuarbeiten, ohne sich um Konflikte oder unerwartete Nebenwirkungen zu kümmern. Unabhängig davon, ob Sie JQuery, React, Angular, Vue oder eine andere Bibliothek oder einen anderen Framework verwenden, können Sie RAMDA verwenden, um saubereren und funktionalen Code zu schreiben.
Ramda ist ein großartiges Werkzeug für Neulinge in der funktionalen Programmierung. Sein API -Design ist einfach und intuitiv und seine Namenskonventionen sind klar und konsistent. Die Dokumentation ist ebenfalls sehr detailliert und es gibt viele Beispiele für den Einstieg. Aber wie jedes neue Tool oder Paradigma gibt es eine Lernkurve. Es kann einige Zeit dauern, bis sich das funktionale Denken gewöhnt und verstehen kann, wie die Funktionen von RAMDA effektiv verwendet werden. Mit der Praxis werden Sie jedoch feststellen, dass es Ihren Code erheblich vereinfachen und das Verständnis erleichtert.
Ramda behandelt Null- und undefinierte Werte als Nullwerte, ähnlich wie andere funktionale Programmiersprachen mit ihnen. Dies bedeutet, dass Sie Null oder undefiniert an Ramdas Funktionen weitergeben können, ohne Fehler oder Ausnahmen zu verursachen. Es ist jedoch eine gute Idee, immer Null- oder undefinierte Werte zu überprüfen, bevor sie an eine Funktion weitergegeben werden, um ein unerwartetes Verhalten zu vermeiden.
Ja, Ramda kann in node.js -Umgebungen verwendet werden. Es ist eine gemeinsame Bibliothek, die in Browsern und Node.js. Sie können es über NPM installieren und benötigen es in Ihrem Node.js -Modul wie jedes andere Paket.
Ramda verfügt über keine integrierte asynchrone Betriebsunterstützung, da es sich hauptsächlich um eine synchrone Bibliothek handelt. Sie können es jedoch mit anderen Bibliotheken verwenden, die asynchrone Operationen unterstützen, wie z. B. Versprechen oder asynchronen/warten. Sie können die Funktionen von Ramda auch in asynchronen Funktionen oder in dann in dann in dann zurück -Rückrufe verwenden.
Ramda ist ein Open -Source -Projekt und kann jederzeit einen Beitrag leisten. Sie können beitragen, indem Sie Fehler melden, neue Funktionen vorschlagen, die Dokumentation verbessern oder Pull -Anfragen senden. Bevor Sie einen Beitrag leisten, lesen Sie am besten die Beitragshandbuch auf der Ramda Github -Seite.
Ja, Ramda hält aktiv und regelmäßig aktualisiert. Wartungspersonal ist verpflichtet, die Bibliothek auf dem neuesten Stand zu halten und Probleme oder Fehler zu lösen, die auftreten. Sie können die GitHub -Seite für die neuesten Updates und Versionen überprüfen.
Ja, Ramda ist unter einer MIT -Lizenz lizenziert, was bedeutet, dass Sie es für kommerzielle Projekte verwenden können. Es ist jedoch eine gute Idee, immer die vollständige Lizenzvereinbarung zu lesen, um Ihre Rechte und Verantwortlichkeiten zu verstehen.
Das obige ist der detaillierte Inhalt vonPraktische funktionale Programmierung mit Ramda.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!