
kontaktiere uns


Ich habe mir die Programmiersprache Elm und das Elm-Framework angesehen. Sie sind ein typischer funktionaler Programmieransatz für das Frontend, der andere beliebte Technologien auf etwas disruptive Weise beeinflusst. Dieser Artikel ist eine Zusammenfassung dessen, was ich über Elm herausgefunden habe.
Dieser Artikel wird in zwei Teile aufgeteilt. In diesem ersten Teil werde ich mich auf die Funktionen konzentrieren, die Elm zu einer interessanten Alternative zu Javascript machen.
Im zweiten Teil werde ich mich auf die historische Perspektive konzentrieren, die Elm einen Blick wert macht; auf die beiden Hauptmerkmale der Sprache eingehen: funktionale Reinheit und statische Typisierung; und schließlich werde ich mir ansehen, wer Elm in der realen Welt verwendet.
Elm ist ein Framework und eine typisierte funktionale Programmiersprache für die Frontend-Entwicklung. Sie inspiriert sich selbst in einer Programmiersprache namens Haskell um Javascript wartbarer zu machen, obwohl es so einfach und nah wie möglich an Javascript gehalten wird. Die Architektur des Frameworks ist ähnlich wie Redux, das war tatsächlich stark von Elm inspiriert.
Vergessen Sie, was Sie über funktionale Programmierung gehört haben. Ausgefallene Worte, seltsame Ideen, schlechte Werkzeuge.
— Evan Czaplicki, Elms Schöpfer
Bei der Gestaltung der Sprache hat Elms Autor beschlossen, den Benutzer in den Mittelpunkt seiner Designentscheidungen zu stellen. Wenn du dir seinen ansiehst“Lass uns Mainstream sein„, Sie werden feststellen, dass ein starker Fokus darauf besteht, wer der Benutzer ist (der Javascript-Programmierer) und was er benötigt, indem Sie die sogenannten Nutzungsorientiertes Design. Diese Philosophie reduziert die Sprachmerkmale auf das Wesentliche und macht das Erlernen ziemlich einfach.
[Ein] kürzlich angestellter Softwaredesigner hatte Quellenlisten auf dem Konferenztisch verteilt und vorsichtig einen Kristall, der an einer langen Kette hing, über den Quellcode gereicht. Hin und wieder markierte der Designer einen roten Kreis auf der Liste. Später fragte einer meiner Kollegen den Designer, was er im Konferenzraum gemacht habe. Die nonchalante Antwort: „Die Fehler in meinem Programm finden“.
Dies ist eine wahre Geschichte. Sie geschah Mitte der 1980er Jahre, als die Menschen große Hoffnungen auf die verborgenen Kräfte in Kristallen hegten.
— MIT-Presse, Einführung in Algorithmen, Achtzehndruck (1997)
Elms Fehlermeldungen sind extrem freundlich. Einerseits ist dies auf das statische Typsystem zurückzuführen, das es dem Compiler ermöglicht, die Unterschiede zwischen den Typen der erwarteten Werte und denen, die für unsere Funktionen bereitgestellt werden, klar zu erkennen und anzugeben. Andererseits ist die Art der Informationen, die in Fehlermeldungen angezeigt werden, sehr bodenständig, da es keine Typklassen gibt:
Zusätzlich zu dieser atypischen Klarheit entschied der Sprachdesigner, dass Fehlermeldungen Priorität haben sollten. Daher gibt der Compiler nicht nur formell an, was mit den Programmen nicht stimmt, sondern gibt auch „Hinweise“ darüber, was die Absicht des Programmierers gewesen sein könnte, und macht Vorschläge für mögliche Korrekturen, zum Beispiel:
[Haskell ist nutzlos.]
— Simon Peyton Jones, Wichtiger Mitwirkender am Design der Haskell-Programmiersprache.
Das stimmt, das ist nein Haskell - Elms Hauptinspirationsquelle. Obwohl Haskell dem nutzungsorientierten Designprozess folgte, wurden viele Funktionen von Haskell nicht benötigt und wurden daher nicht in die Sprache aufgenommen. Dazu gehörte das berüchtigte Typklassensystem.
Dieses System würde all das prätentiös klingende mathematische Vokabular mit sich bringen, das normalerweise unter Haskell-Programmierern zu hören ist, und Elm für den „normalen Joe“ völlig ungeeignet machen.
Aber brauchen wir keine Typklassen? Sie müssen jedem Zweck dienen! Warum braucht Haskell sie und Elm nicht? - Nun, die Antwort hängt von der Problemdomäne ab, die in jeder dieser Sprachen behandelt wird: Haskell ist zwar eine Allzweck-Programmiersprache, Elm jedoch nicht. Einerseits ist Elm einfach eine Frontend-Programmiersprache und kann diese Aufgabe gut erfüllen, ohne auf so viel Komplexität zurückgreifen zu müssen. Andererseits wird ein Teil dessen, was mit dieser Komplexität bewältigt werden soll, von der Elm-Runtime bewältigt und in ihr versteckt — die sich auf domänenspezifische Weise um den Umgang mit Nebenwirkungen und Mutationen kümmert.
Wir hatten keine Laufzeitfehler [...]. Wir hatten auch weniger Fehler, hauptsächlich weil das Typsystem von Elm Sie zwingt, Ihre Domain sorgfältiger zu modellieren. [...] Zusammenfassend lässt sich sagen, dass unser Manager angeordnet hat, dass der gesamte neue Code in Elm geschrieben wird.
— Jeff Schomay, Frontend-Spezialist bei Pivotal Tracker
Das Typensystem von Elm ist sehr sicher und es gibt zwei konstruktive Konsequenzen, die es wert sind, beachtet zu werden:
Mein Ziel war es, sicherzustellen, dass die Verwendung von Referenzen absolut sicher ist, wobei die Überprüfung automatisch vom Compiler durchgeführt wird. Aber ich konnte der Versuchung nicht widerstehen [...]
— Tony Hoare, Erfinder der Nullreferenz
Während andere Programmiersprachen Fehler als Teil der Sprache mit sehr spezifischen Funktionen behandeln — üblicherweise als Exceptions oder Errors bezeichnet — bietet Elm keine spezifischen Primitive, um Fehler auszulösen oder zu behandeln. Die Möglichkeit eines Fehlers wird vielmehr anhand der Typen von Werten modelliert, die von Funktionen zurückgegeben und verarbeitet werden. Einige parametrische Typen können verwendet werden, um Informationen über Fehler zu vermitteln, wie z. B. die Typen Vielleicht
; Ergebnis
und Aufgabe
.
Das Vielleicht
type ist der einfachste von diesen. Er ist definiert als:
Das ein
in diesem Ausdruck kann durch einen bestimmten Typ ersetzt werden, zB einen Wert vom Typ Vielleicht String
kann entweder einen Wert annehmen wie Nur „eine bestimmte Zeichenfolge“
oder Nichts
.
Somit gibt eine Funktion einen Wert von - zum Beispiel - zurück Vielleicht String
kann einen Wert zurückgeben Nur „Ich bin die zurückgegebene Zeichenfolge“
bei Erfolg oder Rückkehr Nichts
beim Scheitern. Der Programmierer ist später immer gezwungen, in beiden Fällen zu entscheiden, was er tun soll, und die Sprache erlaubt das Kompilieren des Programms nicht, wenn beide Möglichkeiten nicht berücksichtigt werden.
Durch den zuvor gezeigten Ansatz vermeidet die Sprache, einen Nullwert zu haben. Und werde so all die Üblichen los undefined ist keine Funktion
Fehler. Wenn es zu einem Fehler kommt, übermittelt der Typ diese Information explizit und der Compiler erzwingt, dass dieser Fall vom Programmierer behandelt wird.
Da Elm eine reine funktionale Sprache ist, besteht der Zweck der Bewertung darin, einen Wert daraus zu ziehen. Daher zwingt Elm den Entwickler, für jede Steueranweisung einen Rückgabewert bereitzustellen. Das bedeutet, dass jeder wenn
Aussage benötigt eine sonst
Klausel und Koffer
Anweisungen müssen jeden möglichen Eingabewert verarbeiten.
Schauen wir uns zum Beispiel einen abstrakten Datentyp an Disziplin beim Tippen
das könnte als Wert angenommen werden Statisch
; Dynamisch
oder Schrittweise
:
und wenn wir einen Wert dieses Typs als Eingabe einer Case-Anweisung (einer Switch-Anweisung) behandeln, aber vergessen, eine der Möglichkeiten zu behandeln:
der Compiler kompiliert das Programm:
Wenn wir also unsere Typen ändern, um mehr Funktionen hinzuzufügen, werden wir vom Compiler darüber informiert, dass etwas Code hinzugefügt werden muss, um mit einer neuen Möglichkeit umzugehen.
Du musst finden, was du liebst.
— Steve Jobs
Ulmen kurze Rückkopplungsschleife und übersichtliche Syntax machen Sie es zu einer sehr angenehmen Arbeitsumgebung. Schauen wir uns an, wie diese Dinge zur Freude der Entwickler von The Elm beitragen.
Vermeiden Sie Erfolg um jeden Preis.
— Simon Peyton Jones, Wichtiger Mitwirkender am Design der Haskell-Programmiersprache.
Eine interessante Konsequenz der zuvor beschriebenen Sicherheitsmerkmale ist, wie sie die Rückkopplungsschleife verkürzen. Die Programmieraktivität besteht in der Regel aus der Iteration der folgenden Aktivitäten:
Im letzten Schritt verbringen die Entwickler oft die meiste Zeit, und diese Zeit wird entweder damit verbracht, automatisierte Tests zu schreiben oder mit dem Programm zu interagieren, um zu bestätigen, dass es korrekt ist. Die meisten Programmierer würden sagen, dass diese Phase am wenigsten Spaß macht.
Elms Sicherheit und das Fehlen von Laufzeitausnahmen überträgt einen Teil der Testen phasenweise in die Kompilieren Phase. Bei der Verwendung von Elm verbringt der Programmierer etwas mehr Zeit mit der Kompilierungsphase — er interagiert mit dem Compiler, bis das Programm als korrekt erachtet wird — und viel weniger Zeit in der Testphase, in der das einzige, was fehlschlagen kann, darin besteht, ob die Geschäftsanforderungen erfüllt sind — und nicht, ob das Programm abstürzt oder nicht.
Bei der Verwendung von Elm erhält der Programmierer früher Feedback zu seinen Fehlern, sodass er nicht so viel Zeit in die langwierige Testphase investieren muss.
Elms Syntax ist von Haskell inspiriert und minimalistisch. Es gibt nur zwei Steueranweisungen und nur sehr wenige reservierte Wörter.
Das Zentrum dieser Syntax ist die Funktion. Wenn das am häufigsten verwendete syntaktische Merkmal einer strukturierten Programmiersprache der Funktionsaufruf ist, warum greifen die meisten Sprachen im Algol-Stil dann auf so viele Sonderzeichen für den Funktionsaufruf und die Definition zurück?
Um die obige Definition und den Aufruf zu schreiben, mussten wir 8 Sonderzeichen für die Funktionsdefinition eingeben:
und 4 beim Funktionsaufruf:
Die Anzahl der gedrückten Zusatztasten hängt von der Sprache Ihrer Tastatur ab. Belästigung und vorzeitige Verletzung durch wiederholte Belastung können variieren.
Elm räumt das auf. Wenn die Funktion so wichtig ist, sollte sie einfach eingegeben und bearbeitet werden können:
Wie Sie sehen, benötigt diese Funktionsdefinition keine Sonderzeichen. Typsignaturen sind optional und werden vom Compiler automatisch abgeleitet, sodass wir schnell experimentieren können, ohne sie explizit eingeben zu müssen. Nichtsdestotrotz sind sie nützlich: Manchmal ist es praktisch, die Typsignatur als Orientierungshilfe beim Schreiben eines weniger offensichtlichen Codeabschnitts zu verwenden, und sie sind oft eine nützliche Form der Dokumentation. Daher werden in Elm Typsignaturen (optional) in einer separaten Zeile geschrieben (einige Editoren generieren die Typsignatur automatisch, wenn wir danach fragen!) :
Ein weiteres Merkmal, das die Verwendung der Sprache ziemlich unterhaltsam macht, ist, dass jede Funktion ein Curry ist und daher auf eine Teilmenge ihrer Argumente angewendet werden kann, wodurch eine sogenannte teilweise angewendete Funktion zurückgegeben wird, die nur auf die fehlenden Argumente wartet. Also der folgende Code:
entspricht dem folgenden Javascript-Code:
Der Hauptvorteil dieser Funktion besteht darin, dass Code, der Funktionen höherer Ordnung verwendet, sehr sauber wird:
Wenn wir diese Operationen jedoch verketten, entsteht ein Meer von verschachtelten Parens, typisch für Lispeln:
Um dieses Problem zu vermeiden, stellt die Sprache die Pipe-Operatoren zur Verfügung (<|
und |>
). Sie ermöglichen die Verkettung von Funktionsanwendungen mit einer Syntax, die dem Durchführen eines Arguments durch eine Transformationspipeline ähnelt:
In ähnlicher Weise; Sie können auch die Komposition verwenden (<<
) oder umgekehrte Komposition (>>
) Operatoren, um dasselbe auszudrücken, ohne explizit auf das Argument verweisen zu müssen, das im Thread ausgeführt wird:
Diese praktisch prägnante Syntax zusammen mit den netten Fehlermeldungen macht Elm am Ende sehr geeignet für interaktive Experimente, sowohl mit der REPL als auch mit dem Compiler.
Wenn Sie ein Elm-Projekt starten, erhalten Sie sofort viele sofort einsatzbereite Funktionen:
Und es lohnt sich, auf einige andere Tools näher einzugehen:
Dies ist eines der Dinge, die Redux durch die Implementierung der Elm-Architektur erhalten hat. Bei der Entwicklung und Erprobung eines Programms sind wir in der Lage, die auf dieser Schnittstelle ausgeführten Aktionen zu überprüfen und in der Zeit vor- und zurückzugehen, um den Status des Programms zu jedem Zeitpunkt seiner Ausführung zu analysieren.
In Redux ist diese Funktionalität aufgrund der Imperativität von Javascript ziemlich fragil, und um damit umzugehen, muss man Folgendes verwenden Unveränderlich oder eine andere Bibliothek, um zu vermeiden, dass der Status der Anwendung direkt verändert wird. In Elm gibt es dieses Problem einfach nicht, weil es auf Sprachebene keine Mutation gibt. Das Sprachdesign selbst schützt uns vor solchen Problemen und vor der Notwendigkeit, zusätzliche Bibliotheken zu verwenden.
Zusätzlich können Sie direkt im Webbrowser mit der Sprache herumspielen - ohne etwas installieren zu müssen. Das Folgende ist ein gutes Beispiel für eine Website, die Live-Editing-Funktionen bietet:
Bei der Veröffentlichung einer neuen Paketversion überprüft das Elm-Tooling, ob die Funktionen, die von unseren Modulen exportiert werden:
Gemäß jeder dieser Möglichkeiten wird sich die Änderung in der Versionsnummer des automatisch berechneten Pakets widerspiegeln, sodass deutlich wird, ob es sich bei den Änderungen um größere Änderungen, geringfügige Änderungen oder Bugfixes handelt und ob es sicher ist, die Version einer verwendeten Bibliothek zu aktualisieren.
In Teil 2 - hier erhältlich - Ich werde darüber sprechen, warum statische Typisierung und funktionale Reinheit gegeben sind, die aktuellen Ökosystemtrends von Javascript. Ich werde auch darüber sprechen, wer Elm benutzt und wie ausgereift es ist. Bitte bleiben Sie dran, ich werde nächste Woche darüber schreiben.
Bei Imaginary Cloud wir haben ein Expertenteam für Softwareentwicklung. Wenn Sie der Meinung sind, dass Sie Hilfe bei Ihrem digitalen Projekt gebrauchen könnten, schreiben Sie uns hier!
Fanden Sie diesen Artikel hilfreich? Diese könnten dir auch gefallen!
Rails-Entwickler mit mehr als 10 Jahren Erfahrung mit verschiedenen Technologien. Ich interessiere mich für funktionale Programmierung.
People who read this post, also found these interesting: