Dies ist eine Fortsetzung des Artikels
„Warum Schläger? Warum Lisp? " Ich schrieb ungefähr ein Jahr, nachdem ich
Racket entdeckt hatte. Als Neuling konnte ich das Lob, das von allen Seiten auf Lisp strömte, nicht verstehen. Ich wusste nicht, was ich denken sollte. Wie man versteht, dass Lisp letztendlich
"tiefe Erleuchtung" verursachen wird. Okay, Bruder, sagst du?
Ich hatte eine einfache Frage:
Was nützt das? In einem früheren Artikel habe ich versucht, darauf zu antworten, und die Gründe zusammengefasst, warum jemand Lisp oder insbesondere Racket lernen möchte.
Ich habe eine Liste der
neun Sprachfunktionen zusammengestellt, die für mich als Neuling bei Racket am wertvollsten sind. Feature Nummer 5 ist beispielsweise „die Erstellung neuer Programmiersprachen“. Diese Methode wird auch als
sprachorientierte Programmierung oder
JOP bezeichnet .
Seitdem ist IOP mein Lieblingsteil von Racket geworden, und ich habe meine Bewunderung in dem Online-Buch
Beautiful Racket geteilt , in dem die ROP-Technik und das Racket-Tool erklärt werden.
Ein Beispiel in meiner Arbeit ist
Pollen . Ich habe diese Programmiersprache für die bequeme Typografie meiner Online-Bücher geschrieben. In Pollen ist der vorherige Absatz wie folgt programmiert:
#lang pollen ◊link["https://beautifulracket.com/appendix/why-racket-why-lisp.html#so-really-whats-in-it-for-me-now"]{ }, Racket. , № 5 — « ». ◊em{- }, ◊em{}.
Ein weiteres Beispiel ist
brag , ein Parser-Generator (im Stil von
lex/yacc
), der
BNF-Grammatik als Quellcode verwendet. Ein einfaches Beispiel für die
bf- Sprache:
#lang brag bf-program : (bf-op | bf-loop)* bf-op : ">" | "<" | "+" | "-" | "." | "," bf-loop : "[" (bf-op | bf-loop)* "]"
Beide Sprachen sind in Racket implementiert und können mit dem üblichen Racket-Interpreter oder in der Racket-IDE (DrRacket genannt) ausgeführt werden.
Hauptprobleme
Und doch ... Trotz der Tatsache, dass das Buch Tausende von Menschen gezwungen hat, Racket zu erkunden, scheint es mir manchmal, dass ich auf den gleichen schnellen Weg gehe wie die Lisp-Fans, die ich einst kritisiert habe.
Wenn NOP so cool ist, warum dann ein paar Tage damit verbringen, ein Buch zu lesen? Richtig? Ich kann alles kurz und ohne weiteres erklären. Zwei einfache Fragen müssen beantwortet werden:
- Welche Probleme eignen sich am besten für die Sprachprogrammierung?
- Warum eignet sich Racket am besten zum Erstellen von Sprachen?
Die zweite Frage ist einfach. Der erste ist nicht. Ich wurde oft gefragt. Ich habe oft den
berühmten Satz von Richter Potter Stewart zitiert: Sie werden ihn verstehen, wenn Sie ihn sehen. Die Antwort ist gut genug für diejenigen, die wirklich interessiert sind. Aber nicht für diejenigen, die auf der Seite stehen und sachliche Argumente hören möchten.
Also werde ich es versuchen. Denken Sie daran, dass ich kein Professor für Informatik bin und nicht über die Theorie der Programmiersprachen sprechen kann. Vielmehr verwende ich Racket und domänenspezifische Sprachen (DSL) für praktische Zwecke: Meine tägliche Arbeit hängt von ihnen ab. Daher werde ich mich auf praktische Aspekte konzentrieren.
Kurze Antwort
- JOP ist eigentlich eine Interface-Design-Methode. Es ist ideal für Aufgaben, die eine minimale Notation bei maximaler Genauigkeit erfordern. Minimale Notation bedeutet die einzig zulässige Notation. Nichts Überflüssiges. Maximale Präzision, dh die Bedeutung dieser Notation, ist genau das, was Sie sagen. Keine Mehrdeutigkeit oder Muster. IOP kommt wie nichts anderes auf den Punkt.
(Ungeduldig kann zu bestimmten Kategorien von Aufgaben übergehen, die von NOP profitieren).
- Racket ist aufgrund seines Makrosystems ideal für OOP. Sie arbeiten im Compiler-Stil und vereinfachen die Codekonvertierung. Das Racket-Makrosystem ist besser als jedes andere.
An dieser Stelle möchte die Hälfte der Leser des Artikels anonyme Kommentare veröffentlichen, in denen meine Thesen kritisiert werden. Aber bitte denken Sie daran: Auf jeden Fall habe ich gewonnen. JOP und Racket haben meine Programmierproduktivität unglaublich gesteigert. Gerne teile ich dieses Wissen mit Ihnen, damit auch Sie diese Vorteile nutzen können. Ich werde mich aber auch freuen, wenn diese Werkzeuge meine Geheimwaffe bleiben. In diesem Fall bleibe ich bei 0,01% der produktivsten Programmierer und erhalte ein beeindruckenderes und profitableres Ergebnis als die restlichen 99,9%.
Sie haben also die Wahl.
Lange Antwort
Wenn Sie über die wichtigsten Fragen nachdenken, kommt es auf eine Meta-Frage an: Warum ist es schwierig, die Vorteile von Atomwaffen zu erklären?
Wenn wir über
Sprachen sprechen, ist der Begriff vielleicht voller Erwartungen darüber, was eine Sprache ist und was sie tut. Während wir uns in diesem Paradigma befinden, ist es schwierig, den Wert von Programmiersprachen zu verstehen.
Wenn Sie jedoch den Umfang verringern und Sprachen als Teil einer breiteren Kategorie von Mensch-Computer-Schnittstellen betrachten, ist es einfacher, die spezifischen Vorteile von OOP zu erkennen. Also lass es uns tun.
Allgemeine Sprachen und domänenspezifische Sprachen
Erstens eine kleine Terminologie. Sprachorientierte Programmierung (auch als OOP bekannt) ist die Idee, Programmierprobleme zu lösen, indem eine neue Sprache erstellt und anschließend ein Programm darauf geschrieben wird. Oft werden solche "kleinen Sprachen" als domänenspezifische Sprachen (DSLs) bezeichnet.
Wie der Name schon sagt, wird eine fachorientierte Sprache an die Aufgaben eines bestimmten Fachgebiets angepasst. Beispielsweise werden PostScript, SQL,
make
, reguläre Ausdrücke,
.htaccess
und HTML als themenorientierte Sprachen betrachtet. Sie versuchen nicht alles zu tun. Sie konzentrieren sich vielmehr darauf, eine Sache gut zu machen.
Am anderen Ende des Spektrums
befinden sich Allzwecksprachen . Hier sehen wir C, Pascal, Perl, Java, Python, Ruby, Racket usw. Warum werden sie nicht als themenorientiert angesehen? Weil sie sich für eine Vielzahl von Computeraufgaben positionieren.
In der Praxis sind Allzwecksprachen häufig auf ein bestimmtes Gebiet spezialisiert. Zum Beispiel ist C für die Systemprogrammierung besser als andere. Perl - für Skripte in der Systemadministration. Python ist eine Sprache für Anfänger. Schläger für sprachorientierte Programmierung. In jedem Fall wurde die Sprache ursprünglich dafür entwickelt.
Es gibt eine feine Linie zwischen DSL und Allzwecksprachen. Zum Beispiel wurde Ruby als Allzwecksprache erstellt, wurde jedoch vor allem für Webanwendungen durch die Verbindung mit Ruby on Rails populär. JavaScript hingegen war ursprünglich eine themenorientierte Sprache für Webbrowserskripte. Aber er mutierte wie ein Virus und ist seitdem weit über die ursprüngliche Aufgabe hinaus gewachsen.
Was ist eine Sprache?
Wenn dieses ganze breite Spektrum Sprachen genannt wird, was sind dann die bestimmenden Merkmale der Sprache?
Ich weiß, was Sie denken: „Hier irren Sie sich. HTML ist keine Sprache. Dies ist nur ein Markup. Er kann den Algorithmus nicht beschreiben. “ Oder: „Reguläre Ausdrücke sind keine Sprache. Sie arbeiten nicht alleine. Es ist nur eine Syntax für eine andere Sprache. "
Das habe ich auch gedacht. Aber je genauer ich hinschaute, desto verschwommener wirkten diese Unterschiede. Daher meine erste Hauptaussage (von drei): Die Programmiersprache ist von Natur aus ein Austauschmedium -
ein Notationssystem, das für Menschen und Computer verständlich ist .
Das Notationssystem (Notation) bedeutet, dass die Sprache eine Syntax hat. "Klar" bedeutet, dass die Sprache mit ihrer Syntax
Bedeutung vermittelt (oder
Semantik , wenn Sie ein ausgefalleneres Wort verwenden). Diese Definition umfasst alle universellen Programmiersprachen. Und alles DSL. (Aber nicht jeder Datenstrom, auf den später noch näher eingegangen wird).
(Obwohl „Programmieren“ und „Sprache“ Wörter sind, die idiomatisch zusammen verwendet werden, werden diese Sprachen nicht nur von Menschen zum Programmieren von Computern verwendet. Manchmal werden sie von Computern verwendet, um mit uns zu kommunizieren (z. B. S-Ausdrücke), manchmal, um miteinander zu kommunizieren (Zum Beispiel XML, JSON, HTML.) Auf jeden Fall scheint es falsch, diese Funktionen auszuschließen. Aber in der Praxis ja - was wir normalerweise mit einer Programmiersprache machen, ist tatsächlich Programmierung).
Betrachten Sie den HTML-Code: eine Möglichkeit, einem Computer - insbesondere einem Webbrowser - mitzuteilen, wie eine Webseite gezeichnet werden soll. Dies ist ein Notationssystem (spitze Klammern, Tags, Attribute usw.), das für Mensch und Computer verständlich ist (das
charset
gibt die Zeichenkodierung an, das
p
Tag enthält einen Absatz usw.).
Hier ist eine kleine HTML-Seite:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>My web page</title> </head> <body> <p>Hello <strong>world</strong></p> </body> <html>
Angenommen, Sie stimmen nicht zu, dass HTML eine Programmiersprache ist. Gut. Wir werden unsere Seite in Python anzeigen. Das ist eine echte Programmiersprache, oder?
print "<!DOCTYPE html>" print "<html>" print "<head>" print "<meta charset=\"UTF-8\">" print "<title>My web page</title>" print "</head>" print "<body>" print "<p>Hello <strong>world</strong></p>" print "</body>" print "<html>"
Wenn Python eine Programmiersprache ist, HTML jedoch nicht, ist dieses Python-Beispiel ein Programm, das HTML-Beispiel jedoch nicht.
Offensichtlich ist dies ein gequälter Unterschied. Hier fügt die Pythonisierung nichts anderes als Komplexität und Stereotypisierung hinzu. Das Pikante ist, dass der einzige interessante semantische Inhalt in einem Python-Programm - unter dem Gesichtspunkt der Verwaltung eines Webbrowsers - darin besteht, dass er in HTML eingebettet ist (möglicherweise können HTML-Tags wie
DOCTYPE
,
meta
und
strong
als Funktionen betrachtet werden, die Argumente annehmen). Die Logik lässt uns zu dem Schluss kommen, dass HTML, obwohl es einfacher und weniger flexibel ist, immer noch eine Programmiersprache ist.
Eingebettete Sprachen
Ein Beispiel mit HTML und Python, das wir uns ausgedacht haben. Das Einbetten von DSL in eine andere Sprache ist jedoch allgegenwärtig. Die auf diese Weise verwendeten Sprachen werden als
eingebettet bezeichnet . Sie stellen die häufigste Form der Sprachprogrammierung dar. Als Programmierer haben Sie sich seit vielen Jahren auf JOP verlassen, auch wenn Sie den Namen nicht kannten.
Zum Beispiel reguläre Ausdrücke (andere Beispiele:
printf
zum Formatieren von Zeichenfolgen, CLDR für Datums- / Zeitmuster, SQL). Wir können uns den regulären Ausdruck nicht als eigenständige Sprache vorstellen. Aber jeder Programmierer weiß, was es ist:
^fo+(bar)*$
Darüber hinaus können Sie diesen regulären Ausdruck wahrscheinlich in Ihre bevorzugte Programmiersprache eingeben und er funktioniert einfach. Dieses konsistente Verhalten ist nur möglich, weil die Notation regulärer Ausdrücke eine externe Sprache (
POSIX ) ist.
Wie bei HTML könnten wir einen äquivalenten Ausdruck in der Notation der Hostsprache schreiben. Beispielsweise unterstützt Racket
Scheme Regular Expressions (SRE): Dies sind reguläre Ausdrücke mit
S-Ausdrucksnotation . Die obige Vorlage wird wie folgt geschrieben:
(seq bos "f" (+ "o") (* (submatch "bar")) eos)
Racket-Programmierer verwenden jedoch selten SRE-Ausdrücke. Sie sind zu lang und schwer zu merken.
Ein weiteres allgegenwärtiges Beispiel für eingebettetes DSL: mathematische Ausdrücke. Jeder Programmierer weiß, was das bedeutet:
(1 + 2) * (3 / 4) - 5
Mathematische Ausdrücke allein erzeugen keine interessanten Programme. Wir müssen sie mit anderen Sprachkonstrukten kombinieren. Aber wie bei regulären Ausdrücken ist dies eine ergonomische und praktische Aufzeichnung. Mathematische Ausdrücke haben ihre eigene Notation und Bedeutung, die sowohl für Menschen als auch für Computer verständlich sind, sodass sie als separate integrierte Sprache gelten.
Scherzen Sie, dass HTML programmiert?
Nein, das ist es. Ich bestätige, dass HTML (sowohl reguläre als auch mathematische Ausdrücke) als rudimentäre Programmiersprachen qualifiziert ist. Dies bedeutet, dass das Schreiben von HTML (oder regulären Ausdrücken oder mathematischen Ausdrücken) als rudimentäre Programmierung gilt.
Bitte keine Panik. Natürlich ist dies ein "Programmierer" auf LinkedIn, der nur HTML- und Arithmetikkenntnisse besitzt. Dies ist Unsinn (obwohl er in einer Woche wahrscheinlich einen Job für 180.000 US-Dollar bekommen wird). Dies ist jedoch eine separate Frage, was „Programmierer“ auf dem Arbeitsmarkt bedeutet. Wir reden nicht darüber.
Turing Totality Trap
Wenn Sie diese Definition von Programmiersprachen immer noch nervt, denken Sie vielleicht, dass eine echte Programmiersprache alle möglichen Algorithmen ausdrücken sollte - das heißt, sie sollte
vollständig sein .
Ich verstehe, dass sich ein solcher Gedanke intuitiv anbietet. Jede universelle Programmiersprache ist Turing vollständig.
Das Problem ist jedoch, dass dies ein niedriger Balken ist. Die Vollständigkeit ist eine technische Metrik, die nicht dem Sprachgebrauch in der realen Welt entspricht. Beispielsweise sind reguläre Ausdrücke nicht vollständig, aber sie sind nützlich, wenn viele Berechnungen mit minimalen Notationen ausgedrückt werden. HTML ist auch nicht vollständig, aber es ist eine nützliche Möglichkeit, den Browser zu steuern. Im Gegenteil, die
bf- Sprache ist Turing vollständig, aber selbst die trivialsten Aufgaben erfordern Kilometer unpassierbaren Codes.
Sprachbeschränkungen
Fällt etwas unter meine Definition von Sprache? Nein.
- Binärdatenformate gelten nicht als Sprachen. Zum Beispiel eine
jpeg
Datei. Obwohl ein Computer sie verstehen kann, tut dies eine Person nicht. Oder PDF: Wenn Sie es hacken, gibt es einige Teile, die für Menschen lesbar sind. Dies liegt jedoch daran, wie PDF funktioniert. Es macht keinen Sinn, Ideen mit PDF-Konstrukten zu schreiben.
- Textdateien sind keine Sprachen. Angenommen, wir haben eine Datei mit Homers Ilias. Wir Menschen können es lesen und verstehen. Obwohl der Computer die Datei trivial verarbeiten kann, indem er beispielsweise ihren Inhalt druckt, ist der darin enthaltene Text für den Computer nicht nachvollziehbar.
- Grafische Benutzeroberflächen sind keine Sprachen. Ja, dies sind Notationssysteme (die auf Text und Bild basieren). Aber sie sind nur für Menschen verständlich. Computer zeichnen eine GUI, verstehen sie aber nicht.
Sprachen als Schnittstellen
Oben habe ich die Programmiersprache als "Medium des Austauschs" zwischen Menschen und Computern beschrieben. Somit passen Sprachen in eine breitere Kategorie, die wir
Schnittstellen nennen.
Dies führt zu der zweiten grundlegenden Aussage (von drei): Die
Sprachprogrammierung ist im Grunde eine Methode zum Entwerfen einer Schnittstelle . Wenn Sie über Schnittstellen nachdenken möchten, wird Ihnen JOP gefallen. Wenn nicht, werden Sie JOP immer noch lieben, weil es Schnittstellen ermöglicht, die sonst nicht erreichbar sind.
Eines meiner Lieblingsbeispiele für eine Sprache als Schnittstelle ist
prahlen , eine mit Racket erstellte Parsergeneratorsprache. Wenn Sie jemals die Lex / Yacc-Toolchain verwendet haben, wissen Sie, dass das Ziel häufig darin besteht, einen Parser aus einer
BNF-Grammatik zu generieren. Zum Beispiel sieht es für
bf so aus:
bf-program : (bf-op | bf-loop)* bf-op : ">" | "<" | "+" | "-" | "." | "," bf-loop : "[" (bf-op | bf-loop)* "]"
Um einen Parser in einer Allzwecksprache zu erstellen, müssen Sie diese Grammatik in eine Reihe von nativem Code übersetzen. Dies ist eine mühsame Arbeit. Und sinnlos - haben wir die Grammatik nicht schon aufgeschrieben? Warum nochmal?
brag
erfüllt jedoch unseren Wunsch. Um den Parser zu erstellen, fügen wir der Datei einfach die Zeile
#Lang brag
, die die BNF-Grammatik auf magische Weise in den Quellcode von
brag
konvertiert:
#Lang brag bf- : (Bf-op | Bf-loop)* bf-op : ">" | "<" | "+" | "-" | "."| "," Bf-loop : "["(Bf-op | Bf-loop)* "]"
Fertig! Bei der Kompilierung exportiert diese Datei die
parse
, die diese BNF-Grammatik implementiert.
Dies ist eines meiner Lieblingsbeispiele, da es anderen Optionen zweifellos überlegen ist. Darüber hinaus ist eine solche Schnittstelle mit einer Allzwecksprache praktisch unmöglich.
Ein JOP-Programmierer erstellt jedoch ständig solche Schnittstellen.
Wo Sprache die beste Schnittstelle ist
Dies bringt mich zu meiner dritten und letzten Grundthese, dass
Sprachen gegenüber Schnittstellen einzigartige Vorteile haben . Natürlich sind die folgenden Kategorien nicht vollständig oder exklusiv. Aber ich habe festgestellt, dass IOP in solchen Situationen viel zu bieten hat:
1. Wenn Sie eine Schnittstelle für weniger erfahrene Programmierer oder Nicht-Programmierer oder faule Programmierer erstellen möchten (unterschätzen Sie nicht die Größe der letzteren Kategorie).
Beispielsweise verfügt Racket über eine ausgefeilte
Webanwendungsbibliothek . Ein einfacher Webserver kann aber auch schnell mit der Sprache
web-server/insta
werden:
#lang web-server/insta (define (start request) (response/xexpr '(html (body "Hello LOP World"))))
Matthew Flatt demonstriert in seinem Artikel
"Erstellen von Sprachen im Schläger" die Sprache, die spielbare
Textabenteuer erzeugt. Wie
brag
sieht es eher nach einer Spezifikation als nach einem Programm aus, aber es funktioniert:
#lang txtadv ===VERBS=== north, n "go north" south, s "go south" get _, grab _, take _ "get" ===THINGS=== ---cactus--- get "Ouch!" ===PLACES=== ---desert--- "You're in a desert. There is nothing for miles around." [cactus, key] north meadow south desert
2. Wenn Sie die Notation vereinfachen möchten. Ein Beispiel sind reguläre Ausdrücke. Ein weiteres Beispiel ist meine fachorientierte Sprache
Pollen zum Schreiben von Online-Büchern. Pollen ähnelt Racket, nur dass Sie hier im Textmodus arbeiten und Sonderzeichen verwenden, um Racket-Befehle anzuzeigen, die in den Inhalt eingebettet sind (Pollen basiert auf der Racket-Dokumentationssprache
Scribble , die den Großteil der Last übernimmt). Der Anfang dieses Absatzes ist also wie folgt programmiert:
. — . — - ◊link["https://pollenpub.com/"]{Pollen} -.
Pollen kümmert sich darum, alle erforderlichen Tags einzufügen und in unfehlbaren HTML-Code umzuwandeln. Ich habe immer noch alle Vorteile des manuellen Markups (volle Kontrolle über die Seite), aber keine Nachteile (z. B. kann ich nicht versehentlich ein nicht geschlossenes Tag hinterlassen).
Ein weiteres Beispiel für eine vereinfachte Notation ist
lindenmayer
, die Fraktalerzeugung und Zeichensprache des
Lindenmayer-Systems wie dieses:
In einem typischen Racket könnte ein Lindenmayer-Programm folgendermaßen aussehen:
#lang racket/base (require lindenmayer/simple/compile) (define (finish val) (newline)) (define (A value) (display 'A)) (define (B value) (display 'B)) (lindenmayer-system (void) finish 3 (A) (A -> AB) (B -> A))
Sie können jedoch die vereinfachte Notation verwenden, indem Sie einfach die
#lang
Notation oben in der Datei ändern:
#lang lindenmayer/simple ## axiom ## A ## rules ## A -> AB B -> A ## variables ## n=3
Die Sprache setzt voraus, dass Sie bereits mit dem L-System vertraut sind. Eine vereinfachte Notation macht es jedoch einfach, Ihre Wünsche in einem Programm aufzuschreiben, das das tut, was Sie wollen.
3. Wenn Sie mit einer vorhandenen Notation arbeiten möchten. Wir haben oben gesehen, wie
brag
BNF-Grammatik als Quellcode verwendet.
#lang brag bf-program : (bf-op | bf-loop)* bf-op : ">" | "<" | "+" | "-" | "." | "," bf-loop : "[" (bf-op | bf-loop)* "]"
Ein weiteres Beispiel. Leute, die Pollen ausprobiert haben, sagten: "Ja, das ist großartig, aber ich bevorzuge Markdown." Kein Problem:
pollen/markdown
ist ein Pollendialekt, der Pollensemantik bietet, aber die übliche Markdown-Notation akzeptiert:
. — . — - [Pollen]("https://pollenpub.com/") -.
Das Schönste? Ich habe diesen Dialekt in nur einer Stunde geschrieben und den
Markdown-Parser mit dem vorhandenen Code kombiniert.
4. Wenn Sie ein Zwischenziel für andere Sprachen erstellen möchten. JSON, YAML, S-Ausdrücke und XML sind fachorientierte Sprachen, die Datenformate für maschinelles Lesen und Schreiben definieren.
In Perfect Racket heißt eine Trainingssprache
jsonic
. Sie können Racket-Ausdrücke in JSON einbetten, wodurch JSON programmierbar wird. Der Quellcode sieht folgendermaßen aus:
#lang jsonic // a line comment [ @$ 'null $@, @$ (* 6 7) $@, @$ (= 2 (+ 1 1)) $@, @$ (list "array" "of" "strings") $@, @$ (hash 'key-1 'null 'key-2 (even? 3) 'key-3 (hash 'subkey 21)) $@ ]
Kompiliert zu regulärem JSON:
[ null, 42, true, ["array","of","strings"], {"key-1":null,"key-3":{"subkey":21},"key-2":false} ]
5. Wenn der Hauptteil des Programms die Konfiguration ist. Beispielsweise können Dotfiles als DSL beschrieben werden. Ein komplexeres Beispiel von Racket ist Jesse Alamas Riposte, eine Sprache zum Testen der JSON-basierten HTTP-API:
#lang riposte $productId := 41966 $qty := 5 $campaignId := 1 $payload := { "product_id": $productId, "campaign_id": $campaignId, "qty": $qty } POST $payload cart/{uuid}/items responds with 200 $itemId := /items/0/cart_item_id GET cart responds with 200
Als Miniatur-Skriptsprache ist Riposte viel intelligenter als die durchschnittliche Punktedatei. Es verbirgt den gesamten für HTTP-Transaktionen erforderlichen Zwischencode und ermöglicht es dem Benutzer, sich auf das Schreiben von Tests zu konzentrieren. Es ist immer noch Hausreinigung. Aber zumindest können Sie sich auf den Haushalt konzentrieren, den Sie interessieren.
Warum Schläger?
Kritiker von JOP fragen oft: „Warum eine fachorientierte Sprache machen? Ist es einfacher, eine native Bibliothek zu schreiben? “
Nein, es ist nicht einfacher, wenn Sie das richtige Werkzeug haben. Schläger ist ungewöhnlich: Er wurde von Grund auf speziell für YOP entwickelt.
Daher ist die Implementierung von DSL auf Racket schneller, billiger und einfacher als Alternativen. In der ersten Lektion meines Buches habe ich beispielsweise gezeigt, wie man in einer Stunde eine neue Sprache entwickelt - auch wenn Sie Racket noch nie verwendet haben.Unter der Haube jedes DSL in Racket funktioniert der Source-to-Source-Compiler tatsächlich , der die DSL-Notation und -Semantik in ein gleichwertiges Racket-Programm konvertiert. Aus diesem Grund kann Racket DSL nicht so schnell ausgeführt werden wie manuell geschriebener C-Code. Dann sind jedoch alle Racket-Tools und -Bibliotheken für jedes DSL verfügbar. Sie verlieren an Produktivität, gewinnen aber immer wieder an Komfort. Und wenn das Erstellen eines DSL bequem und einfach ist, wird es zu einer realistischen Option für eine viel größere Bandbreite von Problemen.Um die Kritik zu beantworten - nein, DSL erfordert nicht unbedingt mehr Arbeit als die native Bibliothek. Darüber hinaus kann eine Sprache, wie wir bereits gesehen haben, als Schnittstelle das tun, was eine native Bibliothek nicht kann.Warum Makro?
Da alle DSLs in Racket kompiliert sind, muss der Programmierer einige Syntaxtransformatoren schreiben, die die DSL-Notation in das native Racket konvertieren. Diese Syntaxkonverter werden als Makros bezeichnet . Tatsächlich können sie als Erweiterungen des Racket-Compilers beschrieben werden.Das Racket-Makrosystem ist riesig, elegant und zweifellos die Perle seiner Krone. Ein Großteil meines Buches handelt von der Freude, mit Racket- Makros zu arbeiten . Ich kann zwei herausragende Funktionen nennen:- Racket , . . , , Racket , , , , , . ( . « » ).
- Schlägermakros sind hygienisch , dh standardmäßig behält der vom Makro erstellte Code den lexikalischen Kontext bei, aus dem das Makro definiert wird. In der Praxis entfällt dadurch die große Menge unnötiger Gesten, die normalerweise für DSL erforderlich sind (weitere Informationen finden Sie im Kapitel Hygiene ).
Ist es möglich, DSL beispielsweise in Python zu implementieren? Natürlich.
Tatsächlich habe ich mein erstes DSL speziell in Python geschrieben - und verwende es immer noch in meiner Schriftdesignarbeit . Nun, das. Einmal war genug. Seitdem benutze ich Racket.Fazit: Sieg mit YaOP
Im Moment können Sie eine von zwei Reaktionen haben:- « , , » . , . , , . . . , . .
- «, , c Racket » . , - Riposte , — ( ):
[ ] - Racket. , , - … : « API , ?» : « Riposte». , , [DSL], , . «» Racket. DSL , .
Am Ende des Artikels „Warum Schläger? Warum Lisp? " Ich sagte, dass die Lisp-Sprache "Ihnen die Möglichkeit gibt, Ihr Potenzial als Programmierer und Denker freizusetzen und dadurch Ihre Erwartungen an das, was Sie erreichen können, zu erhöhen."IOP bietet eine ähnliche Möglichkeit: unsere Erwartungen zu erhöhen, was Programmiersprachen für uns tun können. Sprachen sind keine Black Boxes. Dies sind die Schnittstellen, die wir entwerfen können. Gleichzeitig eröffnen wir neue Möglichkeiten für das, was mit Hilfe von Programmen getan werden kann.Wenn Sie die beste Programmiertechnik finden, verwenden Sie sie. Jetzt, wo ich OOP und Racket habe, werde ich nie mehr zurückkommen.Weiterführende Literatur