Wenn etwas generiert werden kann, dann sind das Daten, kein Code.
Ist diese Idee der Quellcode-Generierung nicht ein Missverständnis? Das heißt, wenn es einen Codegenerator für etwas gibt, warum dann nicht eine ordnungsgemäße Funktion daraus machen, die die erforderlichen Parameter empfangen und die richtige Aktion ausführen kann, die der "erzeugte" Code ausgeführt hätte?
Wenn es aus Performancegründen gemacht wird, dann klingt das nach einem Manko des Compilers.
Wenn es darum geht, zwei Sprachen zu verbinden, dann klingt das nach einem Mangel an Schnittstellenbibliothek.
Vermisse ich hier etwas?
Ich weiß, dass Code auch Daten sind. Was ich nicht verstehe ist, warum Quellcode generieren ? Warum nicht daraus eine Funktion machen, die Parameter akzeptiert und auf diese einwirkt?
flex
oder ein Parser, der von generiertbison
wird, ist mit ziemlicher Sicherheit vorhersehbarer, korrekter und oft schneller auszuführen als in C handgeschriebene Äquivalente. und aus weitaus weniger Code erstellt (was auch weniger Wartungsaufwand bedeutet).Antworten:
Technisch gesehen ist Code, der generiert wird, keine Quelle, selbst wenn es sich um Text handelt, der von Menschen gelesen werden kann. Quellcode ist Originalcode, der von einem Menschen oder einer anderen wahren Intelligenz generiert wurde, nicht mechanisch übersetzt und nicht unmittelbar (direkt oder indirekt) aus einer (wahren) Quelle reproduzierbar ist.
Ich würde sagen, alles sind Daten . Sogar Quellcode. Vor allem Quellcode! Quellcode besteht nur aus Daten in einer Sprache, die für die Ausführung von Programmieraufgaben entwickelt wurde. Diese Daten müssen übersetzt, interpretiert, kompiliert und nach Bedarf in andere Datenformen umgewandelt werden, von denen einige möglicherweise ausführbar sind.
Der Prozessor führt Anweisungen aus dem Speicher aus. Derselbe Speicher, der für Daten verwendet wird. Bevor der Prozessor Befehle ausführt, wird das Programm als Daten in den Speicher geladen .
So sind alle Daten , auch Code .
Es ist vollkommen in Ordnung, mehrere Schritte in der Kompilierung zu haben, von denen einer eine Zwischencodegenerierung als Text sein kann.
Das ist eine Möglichkeit, aber es gibt noch andere.
Nicht alle Textformen sind für den menschlichen Verzehr bestimmt. Insbesondere ist generierter Code (als Text) in der Regel für den Compilerverbrauch und nicht für den menschlichen Verbrauch gedacht .
Der Quellcode wird als das Original betrachtet: der Master - was wir bearbeiten und entwickeln; Was wir mit der Quellcodeverwaltung archivieren. Generierter Code wird in der Regel aus dem ursprünglichen Quellcode neu generiert, auch wenn er für Menschen lesbar ist . Generierter Code muss im Allgemeinen nicht der Quellcodeverwaltung unterliegen, da er während der Erstellung neu generiert wird.
quelle
Praktisches Denken
Ich gehe davon aus, dass Sie in dieser Ausgabe eher praktische Fragen stellen, nicht theoretische Informatik.
Der klassische Grund für die Generierung von Quellcode in statischen Sprachen wie Java war, dass Sprachen wie diese einfach nicht mit benutzerfreundlichen In-Language-Tools für sehr dynamische Aufgaben ausgestattet waren. Zum Beispiel war es in den Anfangszeiten von Java einfach nicht möglich, eine Klasse mit einem dynamischen Namen (der einem Tabellennamen aus einer Datenbank entspricht) und dynamischen Methoden (der Attributen aus dieser Tabelle entspricht) mit dynamischen Datentypen (Matching) zu erstellen die Arten der genannten Attribute). Zumal Java sehr viel Wert darauf legt, dass Tippfehler bei der Kompilierung abgefangen werden können.
In einer solchen Umgebung kann ein Programmierer nur Java-Code erstellen und viele Codezeilen manuell schreiben. Oft wird der Programmierer feststellen, dass er bei jeder Änderung einer Tabelle zurückgehen und den Code entsprechend ändern muss. und wenn er das vergisst, passieren schlimme Dinge. Daher wird der Programmierer an den Punkt gelangen, an dem er einige Werkzeuge schreibt, die dies für ihn tun. Und damit beginnt die Straße zu immer intelligenterer Codegenerierung.
(Ja, Sie könnten den Bytecode im Handumdrehen generieren, aber eine solche Programmierung in Java wäre nichts, was ein zufälliger Programmierer tun würde, wenn er nur ein paar Zeilen Domänencode geschrieben hätte.)
Vergleichen Sie dies mit Sprachen, die sehr dynamisch sind, z. B. Ruby, die ich in den meisten Hinsichten als Gegensatz zu Java betrachten würde (beachten Sie, dass ich dies sage, ohne einen der beiden Ansätze zu bewerten; sie sind einfach unterschiedlich). Hier ist es 100% normal und üblich, zur Laufzeit dynamisch Klassen, Methoden usw. zu generieren, und vor allem kann der Programmierer dies trivial direkt im Code tun, ohne auf eine "Meta" -Ebene zu wechseln. Ja, Dinge wie Ruby on Rails kommen mit der Codegenerierung, aber wir haben in unserer Arbeit festgestellt, dass wir dies im Grunde genommen als eine Art fortgeschrittenen "Tutorial-Modus" für neue Programmierer verwenden, aber nach einer Weile wird es überflüssig (da es so wenig Code gibt) Um in diesem Ökosystem zu schreiben, dass, wenn Sie wissen, was Sie tun, das manuelle Schreiben schneller als das Aufräumen des generierten Codes ist).
Dies sind nur zwei praktische Beispiele aus der "realen Welt". Dann haben Sie Sprachen wie Lisp , wo der Code sind Daten, buchstäblich. Auf der anderen Seite gibt es in kompilierten Sprachen (ohne eine Laufzeit-Engine wie Java oder Ruby) (oder gab es, was ich mit modernen C ++ - Funktionen nicht mithalten konnte ...) einfach kein Konzept, Klassen- oder Methodennamen zur Laufzeit zu definieren. Daher ist die Codegenerierung der Build-Prozess das Werkzeug der Wahl für die meisten Dinge (andere C / C ++ - spezifische Beispiele wären beispielsweise flex, yacc usw.).
quelle
Denn das Programmieren mit Lochkarten (oder Alt-Codes im Notizblock ) ist mühsam.
Wahr. Die Leistung ist mir egal, es sei denn, ich bin dazu gezwungen.
Hmm, keine Ahnung wovon du sprichst.
Sieh mal so aus: Generierter und beibehaltener Quellcode ist immer und für immer ein Ärgernis. Es gibt nur einen Grund. Jemand möchte in einer Sprache arbeiten, während jemand anderes darauf besteht, in einer anderen Sprache zu arbeiten, und keiner kann sich die Mühe machen, herauszufinden, wie man zwischen ihnen interoperiert Sie wollen.
Was in Ordnung ist, bis ich es pflegen muss. An diesem Punkt können Sie alle sterben.
Ist es ein Anti-Muster? Seufz, nein. Viele Sprachen gäbe es nicht einmal, wenn wir nicht bereit wären, uns von den Mängeln früherer Sprachen zu verabschieden und den Code der älteren Sprachen zu generieren, wie viele neue Sprachen anfangen.
Es ist eine Codebasis, die in einem halb umgewandelten Frankenstein-Monster-Patchwork enthalten ist, das ich nicht ausstehen kann. Generierter Code ist unberührbarer Code. Ich hasse es, unantastbaren Code anzusehen. Trotzdem checken die Leute immer wieder ein. WARUM? Sie können auch die ausführbare Datei einchecken.
Nun, jetzt schimpfe ich. Mein Punkt ist, dass wir alle "Code generieren". Wenn du generierten Code wie Quellcode behandelst, machst du mich verrückt. Nur weil es so aussieht, als würde der Quellcode ihn nicht zum Quellcode machen.
quelle
/etc/
Der häufigste Anwendungsfall für Codegeneratoren, mit dem ich in meiner Karriere arbeiten musste, waren Generatoren, die
hat eine Meta-Beschreibung auf hoher Ebene für eine Art Datenmodell oder Datenbankschema als Eingabe verwendet (möglicherweise ein relationales Schema oder eine Art XML-Schema)
und produzierte CRUD-Code für Datenzugriffsklassen als Ausgabe und möglicherweise zusätzliche Dinge wie entsprechende SQLs oder Dokumentation.
Der Vorteil hierbei ist, dass Sie aus einer Zeile einer kurzen Eingabespezifikation 5 bis 10 Zeilen fehlersicheren, typsicheren, fehlerfreien (vorausgesetzt, die Codegeneratorausgabe ist ausgereift) Code erhalten, den Sie ansonsten manuell implementieren und warten mussten. Sie können sich vorstellen, wie sehr dies den Wartungs- und Entwicklungsaufwand verringert.
Lassen Sie mich auch auf Ihre erste Frage antworten
Nein, nicht die eigentliche Generierung von Quellcode, aber es gibt tatsächlich einige Fallstricke. Wie in The Pragmatic Programmer dargelegt , sollte die Verwendung eines Codegenerators vermieden werden, wenn Code erzeugt wird, der schwer zu verstehen ist . Andernfalls kann der erhöhte Aufwand für die Verwendung oder das Debuggen dieses Codes den ersparten Aufwand leicht überwiegen, wenn der Code nicht manuell geschrieben wird.
Ich möchte auch hinzufügen, dass es in den meisten Fällen eine gute Idee ist, generierte Codeteile von manuell geschriebenem Code physisch so zu trennen, dass die Neuerstellung keine manuellen Änderungen überschreibt. Ich habe mich jedoch auch mehrmals mit der Situation befasst, in der die Aufgabe bestand, einen in alter Sprache X geschriebenen Code in eine andere, modernere Sprache Y zu migrieren, mit der Absicht, ihn anschließend in Sprache Y zu pflegen. Dies ist eine gültige Verwendung Fall für die einmalige Codegenerierung.
quelle
Ich habe zwei Anwendungsfälle für generierten (zum Zeitpunkt der Erstellung und nie eingecheckten) Code festgestellt:
quelle
Sussmann hatte in seinem Klassiker "Struktur und Interpretation von Computerprogrammen" viel Interessantes darüber zu sagen, vor allem über die Code-Daten-Dualität.
Für mich besteht der Hauptzweck der Ad-hoc-Codegenerierung darin, mithilfe eines verfügbaren Compilers eine kleine domänenspezifische Sprache in etwas zu konvertieren, das ich in meine Programme einbinden kann. Denken Sie an BNF, denken Sie an ASN1 (eigentlich nicht, es ist hässlich), denken Sie an Tabellenkalkulationen für Datenwörterbücher.
Triviale domänenspezifische Sprachen können eine enorme Zeitersparnis bedeuten, und die Ausgabe von Daten, die mit Standard-Sprachwerkzeugen kompiliert werden können, ist der richtige Weg, wenn Sie solche Dinge erstellen, die Sie lieber bearbeiten, einen nicht trivialen handgehackten Parser in einer beliebigen Muttersprache schreiben, oder die BNF für eine automatisch generierte?
Durch die Ausgabe von Text, der dann einem System-Compiler zugeführt wird, erhalte ich all diese Compiler-Optimierung und systemspezifische Konfiguration, ohne darüber nachdenken zu müssen.
Ich verwende die Compiler-Eingabesprache effektiv nur als Zwischenrepräsentation. Was ist das Problem? Textdateien sind nicht von Natur aus Quellcode, sie können eine IR für einen Compiler sein , und wenn sie zufällig wie C oder C ++ oder Java oder was auch immer aussehen, wen interessiert das?
Nun , wenn Sie sind schwer zu denken , Sie könnten die Ausgabe der Spielzeug Sprache Parser bearbeiten, die eindeutig das nächste Mal , wenn jemand bearbeitet die Eingangssprachdateien enttäuschen wird und neu erstellt, die Antwort ist nicht die Auto Commit IR an die Repo erzeugt, hat es generiert durch Ihre Toolchain (und vermeiden Sie, dass solche Leute in Ihrer Entwicklergruppe sind, sie arbeiten normalerweise glücklicher im Marketing).
Dies ist weniger ein Mangel an Ausdruckskraft in unseren Sprachen als vielmehr ein Ausdruck der Tatsache, dass Sie manchmal Teile der Spezifikation in eine Form bringen (oder massieren) können, die automatisch in Code umgewandelt werden kann und in der Regel weitaus weniger ergibt Bugs und weitaus einfacher zu pflegen. Wenn ich unseren Test- und Konfigurationsmitarbeitern eine Tabelle geben kann, die sie optimieren können, und ein Tool, das sie dann ausführen, das diese Daten aufnimmt und eine vollständige Hex-Datei für den Flash auf meinem Steuergerät ausspuckt, ist das eine enorme Zeitersparnis gegenüber der manuellen Übersetzung das neueste Setup in einer Reihe von Konstanten in der Sprache des Tages (komplett mit Tippfehlern).
Das Gleiche gilt für das Erstellen von Modellen in Simulink und das anschließende Generieren von C mit RTW. Anschließend wird die Kompilierung mit einem beliebigen Werkzeug durchgeführt. Das Zwischen-C ist nicht lesbar. Das Matlab RTW-Zeug auf hoher Ebene muss nur eine Teilmenge von C kennen, und der C-Compiler kümmert sich um die Plattformdetails. Das einzige Mal, wenn ein Mensch durch das generierte C stöbern muss, ist, dass die RTW-Skripte einen Fehler aufweisen, und so etwas ist mit einer nominal vom Menschen lesbaren IR viel einfacher zu debuggen als mit nur einem binären Analysebaum.
Sie können solche Dinge natürlich schreiben, um Bytecode oder sogar ausführbaren Code auszugeben, aber warum sollten Sie das tun? Wir haben Werkzeuge, um eine IR in diese Dinge umzuwandeln.
quelle
Pragmatische Antwort: Ist die Codegenerierung notwendig und nützlich? Stellt es etwas bereit, das wirklich sehr nützlich und für die proprietäre Codebasis erforderlich ist, oder scheint es nur eine andere Möglichkeit zu schaffen, Dinge auf eine Weise zu tun, die mehr intellektuellen Aufwand für suboptimale Ergebnisse mit sich bringt?
Wenn Sie diese Frage stellen müssen und es keine eindeutige Antwort gibt, ist die Codegenerierung wahrscheinlich überflüssig und trägt lediglich zur Exotik und zu einem hohen intellektuellen Aufwand für Ihre Codebasis bei.
In der Zwischenzeit können Sie OpenShadingLanguage verwenden: https://github.com/imageworks/OpenShadingLanguage
... dann müssen solche Fragen nicht gestellt werden, da sie durch die eindrucksvollen Ergebnisse sofort beantwortet werden.
In einem solchen Fall müssen Sie die Existenz des Codegenerators nicht in Frage stellen. Wenn Sie in dieser Art von VFX-Domain arbeiten, lautet Ihre sofortige Antwort in der Regel eher "Halt die Klappe und nimm mein Geld!" oder "Wow, wir müssen auch so etwas machen."
quelle
Nein, das Generieren von Zwischencode ist kein Anti-Pattern. Die Antwort auf den anderen Teil Ihrer Frage "Warum?" Ist eine sehr breite (und getrennte) Frage, obwohl ich trotzdem einige Gründe nennen werde.
Historische Konsequenzen, wenn man nie von Menschen lesbaren Code hat
Nehmen wir C und C ++ als Beispiele, da sie zu den bekanntesten Sprachen gehören.
Beachten Sie, dass bei der logischen Verarbeitung des Kompilierens von C-Code kein Maschinencode, sondern von Menschen lesbarer Assemblycode ausgegeben wird. Ebenso werden alte C ++ - Compiler verwendet, um C ++ - Code physisch in C-Code zu kompilieren. In dieser Ereigniskette können Sie vom lesbaren Code 1 zum lesbaren Code 2 zum lesbaren Code 3 zum Maschinencode kompilieren. "Warum?" Warum nicht?
Wenn Zwischen, für Menschen lesbaren Code nie erzeugt wurde, könnten wir nicht einmal haben C oder C ++ überhaupt. Das ist sicherlich eine Möglichkeit; Menschen beschreiten den Weg des geringsten Widerstands gegen ihre Ziele, und wenn eine andere Sprache aufgrund von C-Entwicklungsstagnation zuerst Dampf gewann, wäre C möglicherweise gestorben, als es noch jung war. Natürlich könnte man argumentieren "Aber dann würden wir vielleicht eine andere Sprache verwenden, und vielleicht wäre es besser." Vielleicht oder vielleicht wäre es schlimmer. Oder vielleicht würden wir alle noch in der Versammlung schreiben.
Warum von Menschen lesbaren Zwischencode verwenden?
Beispiel
Ich habe bereits an Projekten gearbeitet, bei denen Code auf der Grundlage von Daten oder Informationen in einem anderen Dokument generiert werden muss. In einem Projekt wurden beispielsweise alle Netzwerknachrichten und konstanten Daten in einer Tabelle definiert und ein Tool, das die Tabelle durchläuft und eine Menge C ++ - und Java-Code generiert, mit dem wir mit diesen Nachrichten arbeiten können.
Ich sage nicht, dass dies der beste Weg war, um dieses Projekt einzurichten (ich war nicht Teil seines Startups), aber das war es, was wir hatten, und es waren Hunderte (vielleicht sogar Tausende, nicht sicher) von Strukturen, Objekten und Konstanten das wurden erzeugt; Zu diesem Zeitpunkt ist es wahrscheinlich zu spät, um es in so etwas wie Rhapsody noch einmal zu versuchen. Aber selbst wenn es in so etwas wie Rhapsody überarbeitet wurde, haben wir trotzdem Code, der aus Rhapsody generiert wurde .
Außerdem war es in einer Hinsicht gut, all diese Daten in einer Tabelle zu haben: Es ermöglichte uns, die Daten auf eine Weise darzustellen, die wir nicht hätten, wenn sie alle nur in Quellcodedateien wären.
Beispiel 2
Als ich in der Compilerkonstruktion gearbeitet habe, habe ich das Tool Antlr zum Lexen und Parsen verwendet. Ich habe eine Sprachgrammatik angegeben, dann habe ich mit dem Tool eine Menge Code in C ++ oder Java ausgespuckt, dann habe ich diesen generierten Code neben meinem eigenen Code verwendet und ihn in den Build aufgenommen.
Wie hätte das anders gemacht werden sollen? Vielleicht könntest du dir einen anderen Weg einfallen lassen; es gibt wahrscheinlich andere möglichkeiten. Aber für diese Arbeit wären die anderen Möglichkeiten nicht besser gewesen als der generierte Lex / Parse-Code, den ich hatte.
quelle
Was Sie vermissen, ist die Wiederverwendung .
Wir haben ein erstaunliches Werkzeug, um Quelltext in Binärcode umzuwandeln, einen so genannten Compiler. Die Eingaben sind gut definiert (normalerweise!), Und es wurde viel gearbeitet, um die Optimierung zu verfeinern. Wenn Sie wirklich wollen , verwenden Sie den Compiler einige Operationen durchzuführen, möchten Sie einen vorhandenen Compiler verwenden und nicht Ihr eigenes schreiben.
Viele Leute erfinden neue Programmiersprachen und schreiben ihre eigenen Compiler. Ziemlich ausnahmslos tun sie dies alle, weil sie die Herausforderung genießen und nicht, weil sie die Funktionen benötigen, die diese Sprache bietet. Alles, was sie tun, könnte in einer anderen Sprache erfolgen; Sie erstellen einfach eine neue Sprache, weil sie diese Funktionen mögen. Was ihnen das allerdings nicht bringt, ist ein gut abgestimmter, schneller, effizienter und optimierender Compiler. Es wird ihnen etwas bringen, das Text in Binärdateien verwandeln kann, aber es wird nicht so gut sein wie alle existierenden Compiler .
Text ist nicht nur etwas, was Menschen lesen und schreiben. Computer sind auch mit Text perfekt zu Hause. Tatsächlich sind Formate wie XML (und andere verwandte Formate) erfolgreich, weil sie einfachen Text verwenden. Binärdateiformate sind oft undeutlich und schlecht dokumentiert, und ein Leser kann nicht leicht herausfinden, wie sie funktionieren. XML ist relativ selbstdokumentierend und erleichtert es den Benutzern, Code mit XML-formatierten Dateien zu schreiben. Alle Programmiersprachen können Textdateien lesen und schreiben.
Angenommen, Sie möchten eine neue Einrichtung hinzufügen, um Ihr Leben zu erleichtern. Vielleicht ist es ein GUI-Layout-Tool. Vielleicht sind es die Schnittstellen für Signale und Slots, die Qt bereitstellt. Vielleicht können Sie mit TIs Code Composer Studio das Gerät, mit dem Sie arbeiten, auf diese Weise konfigurieren und die richtigen Bibliotheken in den Build ziehen. Möglicherweise werden ein Datenwörterbuch und automatisch generierte Typendefinitionen sowie Definitionen globaler Variablen benötigt (ja, dies ist in eingebetteter Software immer noch sehr wichtig). Was auch immer es ist, die effizienteste Möglichkeit, Ihren vorhandenen Compiler zu nutzen, besteht darin, ein Tool zu erstellen, das Ihre Konfiguration von what-it-is übernimmt und automatisch Code in der Sprache Ihrer Wahl erstellt.
Es ist einfach zu entwickeln und zu testen, da Sie wissen, was läuft, und Sie können den Quellcode lesen, den es ausspuckt. Sie müssen nicht viele Jahre damit verbringen, einen Compiler zu erstellen, der mit GCC mithalten kann. Sie müssen keine komplett neue Sprache lernen oder andere dazu auffordern. Alles, was Sie tun müssen, ist, diesen einen kleinen Bereich zu automatisieren, und alles andere bleibt gleich. Job erledigt.
quelle
Eine etwas pragmatischere Antwort, die sich auf das Warum und nicht auf das konzentriert, was Quellcode ist und was nicht. Beachten Sie, dass das Generieren von Quellcode in all diesen Fällen Teil des Erstellungsprozesses ist. Daher sollten die generierten Dateien nicht in die Quellcodeverwaltung gelangen.
Interoperabilität / Einfachheit
Ein gutes Beispiel sind die Protokollpuffer von Google: Sie schreiben eine einzige Protokollbeschreibung auf hoher Ebene, mit der die Implementierung in mehreren Sprachen erstellt werden kann. Oftmals werden verschiedene Teile des Systems in verschiedenen Sprachen geschrieben.
Implementierung / technische Gründe
Verwenden Sie TypeScript - Browser können es nicht interpretieren, sodass der Erstellungsprozess einen Transpiler (Code-to-Code-Übersetzer) verwendet, um JavaScript zu generieren. Tatsächlich beginnen viele neue oder esoterisch kompilierte Sprachen mit dem Transpilieren nach C, bevor sie einen richtigen Compiler erhalten.
Benutzerfreundlichkeit
Für eingebettete Projekte (Think IoT), die in C geschrieben sind und nur eine einzige Binärdatei (RTOS oder kein Betriebssystem) verwenden, ist es ziemlich einfach, ein C-Array mit den Daten zu generieren, die wie normaler Quellcode kompiliert werden sollen, anstatt sie direkt zu verknüpfen als Ressourcen.
Bearbeiten
Erweiterung von protobuf: Mit der Codegenerierung können die generierten Objekte erstklassige Klassen in jeder Sprache sein. In einer kompilierten Sprache würde ein generischer Parser zwangsläufig eine Schlüsselwertstruktur zurückgeben - was bedeutet, dass Sie viel Code für das Boilerplate benötigen, einige Überprüfungen zur Kompilierungszeit (insbesondere für Schlüssel und Wertetypen) verpassen und eine schlechtere Leistung erzielen keine Code-Vervollständigung. Stellen Sie sich vor, dass alle
void*
in C oder so großenstd::variant
in C ++ (wenn Sie C ++ 17 haben), einige Sprachen möglicherweise überhaupt keine solche Funktion haben.quelle
Es ist eine Umgehungslösung für eine nicht ausreichend ausdrucksstarke Programmiersprache. Es ist nicht erforderlich, Code in einer Sprache zu generieren, die eine angemessene integrierte Metaprogrammierung enthält.
quelle
Die Generierung von Quellcode ist nicht immer ein Anti-Pattern. Zum Beispiel schreibe ich gerade ein Framework, das gemäß vorgegebener Spezifikation Code in zwei verschiedenen Sprachen (Javascript und Java) generiert. Das Framework verwendet das generierte Javascript, um Browseraktionen des Benutzers aufzuzeichnen, und verwendet den Java-Code in Selenium, um die Aktion tatsächlich auszuführen, wenn sich das Framework im Wiedergabemodus befindet. Wenn ich keine Codegenerierung verwenden würde, müsste ich manuell sicherstellen, dass beide immer synchron sind, was umständlich ist und in gewisser Weise auch eine logische Verdoppelung darstellt.
Wenn man jedoch die Quellcodegenerierung verwendet, um Funktionen wie Generika zu ersetzen, ist dies ein Anti-Pattern.
quelle
Vielleicht ein gutes Beispiel, bei dem sich der Zwischencode als Grund für den Erfolg herausstellte? Ich kann Ihnen HTML anbieten.
Ich glaube, es war wichtig, dass HTML einfach und statisch war - es machte es einfach, Browser zu erstellen, es ermöglichte das frühe Starten von mobilen Browsern usw. Wie weitere Experimente (Java-Applets, Flash) zeigten, führten komplexere und leistungsfähigere Sprachen zu mehr Problemen . Es stellt sich heraus, dass Benutzer tatsächlich durch Java-Applets gefährdet sind und der Besuch solcher Websites genauso sicher war wie das Ausprobieren von Spiel-Cracks, die über DC ++ heruntergeladen wurden. Plain HTML hingegen ist harmlos genug, um Websites mit angemessenem Vertrauen in die Sicherheit unseres Geräts zu überprüfen.
HTML wäre jedoch bei weitem nicht dort, wo es jetzt ist, wenn es nicht computergeneriert wäre. Meine Antwort wurde erst auf dieser Seite angezeigt, wenn jemand sie manuell aus der Datenbank in eine HTML-Datei geschrieben hat. Zum Glück können Sie HTML in fast jeder Programmiersprache nutzbar machen :)
Können Sie sich eine bessere Möglichkeit vorstellen, die Frage sowie alle Antworten und Kommentare für den Benutzer anzuzeigen, als HTML als generierten Zwischencode zu verwenden?
quelle
Weil es schneller und einfacher (und weniger fehleranfällig) ist, als den Code manuell zu schreiben, insbesondere bei langwierigen, sich wiederholenden Aufgaben. Sie können auch das übergeordnete Tool verwenden, um Ihr Design zu überprüfen und zu validieren, bevor Sie eine einzelne Codezeile schreiben.
Häufige Anwendungsfälle:
Beachten Sie, dass es sich bei keiner der oben genannten Umgebungen um eigenständige Ausführungsumgebungen handelt. Es gibt keine Möglichkeit, Ihren Code mit ihnen zu verknüpfen.
quelle
Manchmal verfügt Ihre Programmiersprache einfach nicht über die von Ihnen gewünschten Funktionen, sodass es tatsächlich unmöglich ist, Funktionen oder Makros zu schreiben, um das zu tun, was Sie möchten. Oder vielleicht könnten Sie tun, was Sie wollen, aber der Code zum Schreiben wäre hässlich. Ein einfaches Python-Skript (oder ähnliches) kann dann den erforderlichen Code als Teil Ihres Erstellungsprozesses generieren, den Sie dann
#include
in die eigentliche Quelldatei einfügen.Woher weiß ich das? Da es sich um eine Lösung handelt, zu der ich bei der Arbeit mit verschiedenen Systemen, zuletzt SourcePawn, mehrmals gelangt bin. Ein einfaches Python-Skript, das eine einfache Zeile Quellcode analysiert und zwei oder drei Zeilen generierten Codes erzeugt, ist weitaus besser, als den generierten Code manuell zu erstellen, wenn Sie am Ende zwei Dutzend solcher Zeilen haben (alle meine cvars erstellen).
Demonstrativer / Beispiel-Quellcode verfügbar, wenn die Leute es wollen.
quelle
Textform ist für den einfachen Verzehr durch Menschen erforderlich. Computer verarbeiten auch Code in Textform ganz einfach. Aus diesem Grund sollte generierter Code in der Form generiert werden, die am einfachsten zu generieren und am einfachsten von Computern zu verarbeiten ist und die sehr oft lesbaren Text enthält.
Und wenn Sie Code generieren, muss der Code-Generierungsprozess selbst häufig von Menschen getestet werden. Es ist sehr, sehr nützlich, wenn der generierte Code von Menschen gelesen werden kann, damit Menschen Probleme bei der Codegenerierung erkennen können. Schließlich muss jemand den Code schreiben, um Code zu generieren. Es passiert nicht aus der Luft.
quelle
Code wird nur einmal generiert
Nicht die gesamte Generierung von Quellcode besteht darin, Code zu generieren und ihn dann nie zu berühren. Generieren Sie es dann aus der ursprünglichen Quelle, wenn es aktualisiert werden muss.
Manchmal generieren Sie Code nur einmal, verwerfen dann die ursprüngliche Quelle und behalten die neue Quelle bei, wenn Sie fortfahren.
Dies passiert manchmal, wenn Code von einer Sprache in eine andere portiert wird. Besonders wenn man nicht erwartet, dass man später über neue Änderungen im Original portieren möchte (z. B. wird der alte Sprachcode nicht beibehalten oder ist tatsächlich vollständig (z. B. im Fall einiger mathematischer Funktionen)).
Ein häufiger Fall ist, dass das Schreiben eines Codegenerators zu diesem Zweck möglicherweise nur 90% des Codes korrekt übersetzt. und dann müssen die letzten 10% von Hand repariert werden. Das ist viel schneller als 100% von Hand zu übersetzen.
Solche Codegeneratoren unterscheiden sich oft sehr von der Art der Codegeneratoren, die Vollsprachenübersetzer (wie Cython oder
f2c
) produzieren. Da ist das Ziel, den Code einmalig zu pflegen. Sie werden oft als eine 1 gemacht, um genau das zu tun, was sie müssen. In vielerlei Hinsicht ist es die nächste Version der Verwendung eines regulären Ausdrucks / Find-Replace-to-Port-Codes. "Tool assisted porting" könnte man sagen.Einmaliges Generieren von Code, z. B. von einer Website aus.
Eng verwandt ist, wenn Sie den Code aus einer Quelle generieren, auf die Sie nicht erneut zugreifen möchten. ZB wenn die zum Generieren des Codes erforderlichen Aktionen nicht wiederholbar oder konsistent sind oder deren Ausführung teuer ist. Ich arbeite gerade an zwei Projekten: DataDeps.jl und DataDepsGenerators.jl .
DataDeps.jl hilft Benutzern beim Herunterladen von Daten (wie Standard-ML-Datasets). Dazu benötigt es einen sogenannten RegistrationBlock. Dies ist ein Code, der einige Metadaten angibt, z. B. den Ort, von dem die Dateien heruntergeladen werden sollen, sowie eine Prüfsumme und eine Meldung, in der dem Benutzer Begriffe / Codierungen / der Lizenzstatus der Daten erläutert werden.
Das Schreiben dieser Blöcke kann ärgerlich sein. Und diese Informationen sind häufig (strukturiert oder unstrukturiert) auf den Websites verfügbar, auf denen die Daten gehostet werden. Daher verwendet DataDepsGenerators.jl einen Webscraper, um den RegistrationBlockCode für einige Sites zu generieren, die viele Daten hosten.
Möglicherweise werden sie nicht korrekt generiert. Der Entwickler, der den generierten Code verwendet, kann und sollte ihn überprüfen und korrigieren. Vermutlich möchten sie sicherstellen, dass die Lizenzinformationen nicht übersehen werden.
Wichtig ist, dass Benutzer / Entwickler, die mit DataDeps.jl arbeiten, den Webscraper nicht installieren oder verwenden müssen, um den generierten RegistrationBlock-Code zu verwenden. (Und das Nicht-Herunterladen und Installieren eines Web-Scrapers spart einiges an Zeit. Insbesondere für die CI-Läufe.)
Einmal generierter Quellcode ist kein Gegenmuster. und es kann normalerweise nicht durch Metaprogrammierung ersetzt werden.
quelle
f2c
+ verwendencc
), aber der resultierende Code war nicht wirklich ein guter Ausgangspunkt für eine C-Version des Programms, AFAIK.f2c
)sed
geht ein langer Weg, aber manchmal braucht man ein bisschen mehr Ausdruckskraft. Die Grenze zwischen Programmlogik und Daten ist oft fein. Manchmal ist die Unterscheidung nicht sinnvoll. JSON ist (/ war) nur JavaScript-Objektkonstruktorcode. In meinem Beispiel generiere ich auch Objektkonstruktorcode (sind es Daten? Vielleicht (vielleicht nicht, weil es manchmal Funktionsaufrufe hat). Wird es besser als Code behandelt? Ja.)Die Generierung von "Quellcode" ist ein Hinweis auf einen Mangel der generierten Sprache. Ist der Einsatz von Werkzeugen zur Überwindung dieses Problems ein Widerspruch? Absolut nicht - lass es mich erklären.
In der Regel wird die Codegenerierung verwendet, da eine Definition auf höherer Ebene vorhanden ist, die den resultierenden Code viel weniger ausführlich beschreiben kann als die Sprache auf niedrigerer Ebene. Die Codegenerierung erleichtert somit die Effizienz und Kürze.
Wenn ich c ++ schreibe, tue ich das, weil ich damit effizienter Code schreiben kann als mit Assembler- oder Maschinencode. Der Compiler generiert weiterhin Maschinencode. Am Anfang war c ++ einfach ein Präprozessor, der C-Code generierte. Allzwecksprachen eignen sich hervorragend zum Generieren von Allzweckverhalten.
Auf die gleiche Weise ist es mit einer DSL (domänenspezifischen Sprache) möglich, knappen, aber möglicherweise auf eine bestimmte Aufgabe beschränkten Code zu schreiben. Dadurch wird es weniger kompliziert, das richtige Verhalten des Codes zu generieren. Denken Sie daran, dass Code Mittel und Zweck ist . Was ein Entwickler sucht, ist eine effiziente Möglichkeit, Verhalten zu generieren.
Im Idealfall kann der Generator schnellen Code aus einer Eingabe erstellen, die einfacher zu bearbeiten und zu verstehen ist. Wenn dies erfüllt ist, ist die Nichtverwendung eines Generators ein Anti-Pattern . Dieses Anti-Pattern kommt in der Regel von der Vorstellung, dass "reiner" Code "sauberer" ist, ähnlich wie ein Holzarbeiter oder ein anderer Handwerker die Verwendung von Elektrowerkzeugen oder die Verwendung von CNC zum "Erzeugen" von Werkstücken sieht (denken Sie an Gold) Hammer ).
Wenn es andererseits schwieriger ist, den Quellcode zu verwalten oder zu generieren, der nicht effizient genug ist, gerät der Benutzer in die Falle, die falschen Tools zu verwenden (manchmal aufgrund desselben goldenen Hammers ).
quelle
Die Generierung von Quellcode bedeutet auf jeden Fall, dass der generierte Code Daten sind. Aber es sind erstklassige Daten, Daten, die der Rest des Programms manipulieren kann.
Die beiden gebräuchlichsten Datentypen, die mir bekannt sind und in den Quellcode integriert sind, sind grafische Informationen zu Fenstern (Anzahl und Platzierung verschiedener Steuerelemente) und ORMs. In beiden Fällen erleichtert die Integration über die Codegenerierung die Manipulation der Daten, da Sie keine zusätzlichen "speziellen" Schritte durchführen müssen, um sie zu verwenden.
Bei der Arbeit mit den Original-Macs (1984) wurden Dialog- und Fensterdefinitionen mit einem Ressourcen-Editor erstellt, der die Daten in einem Binärformat hielt. Die Verwendung dieser Ressourcen in Ihrer Anwendung war schwieriger als wenn das "Binärformat" Pascal gewesen wäre.
Nein, die Generierung von Quellcode ist kein Anti-Pattern, sondern ermöglicht es, die Daten in die Anwendung einzubeziehen, was die Verwendung vereinfacht.
quelle
Code-Generierung ist ein Anti-Pattern, wenn es mehr kostet als es leistet. Diese Situation tritt auf, wenn die Generierung von A nach B erfolgt, wobei A fast dieselbe Sprache wie B ist, jedoch mit einigen geringfügigen Erweiterungen, die durch einfaches Codieren in A mit weniger Aufwand als alle benutzerdefinierten Tools und Build-Staging-Vorgänge für A nach B ausgeführt werden können .
Der Kompromiss ist für die Codegenerierung in Sprachen, die keine Metaprogrammiermöglichkeiten (Strukturmakros) haben, untragbarer, da die Metaprogrammierung durch die Bereitstellung externer Textverarbeitung kompliziert und unzureichend ist.
Der schlechte Kompromiss könnte auch mit der Nutzungsmenge zu tun haben. Sprache A kann sich erheblich von B unterscheiden, aber das gesamte Projekt mit seinem benutzerdefinierten Codegenerator verwendet A nur an ein oder zwei kleinen Stellen, sodass die Gesamtkomplexität (kleine Bits von A plus A -> B-Codegenerator, plus das umgebende Build-Staging) übersteigt die Komplexität einer soeben in B durchgeführten Lösung.
Grundsätzlich sollten wir, wenn wir uns zur Codegenerierung verpflichten, wahrscheinlich "groß rausgehen oder nach Hause gehen": dafür sorgen, dass es eine substantielle Semantik hat und viel verwendet wird, oder uns nicht darum kümmern.
quelle
Ich habe diese Aussage nicht klar gesehen (ich habe gesehen, dass sie von ein oder zwei Antworten berührt wurde, aber sie schien nicht sehr klar zu sein)
Das Generieren von Code (wie Sie sagten, als ob es Daten wären) ist kein Problem - es ist eine Möglichkeit, einen Compiler für einen sekundären Zweck wiederzuverwenden.
Das Bearbeiten von generiertem Code ist eines der heimtückischsten, bösesten und schrecklichsten Anti-Patterns, denen Sie jemals begegnen werden. Mach das nicht.
Bestenfalls zieht die Bearbeitung des generierten Codes eine Menge schlechten Codes in Ihr Projekt (der GESAMTE Codesatz ist jetzt wirklich SOURCE CODE - keine Daten mehr). Im schlimmsten Fall ist der Code, der in Ihr Programm geladen wird, hochgradig redundant und hat einen schlechten Namen.
Ich nehme an, eine dritte Kategorie ist Code, den Sie einmal verwenden (GUI-Generator?) Und dann bearbeiten, um Ihnen den Einstieg / das Lernen zu erleichtern. Dies ist ein kleiner Teil von jedem - es kann ein guter Start sein, aber Ihr GUI-Generator wird darauf abzielen, "generierbaren" Code zu verwenden, der für Sie als Programmierer kein guter Start ist versucht, es erneut für eine zweite GUI zu verwenden, was bedeutet, redundanten SOURCE-Code in Ihr System zu ziehen.
Wenn Ihre Werkzeuge so intelligent sind, dass keine Änderungen am generierten Code zulässig sind, können Sie sie ausführen. Wenn nicht, würde ich es als eines der schlimmsten Anti-Patterns bezeichnen.
quelle
Code und Daten sind beide: Information.
Daten sind die Informationen genau in der Form, die Sie benötigen (und Wert). Code ist ebenfalls Information, jedoch in indirekter oder intermediärer Form. Code ist im Wesentlichen auch eine Form von Daten.
Insbesondere ist Code eine Information für Maschinen, mit der Menschen von der Verarbeitung von Informationen allein entlastet werden können.
Das wichtigste Motiv ist die Entlastung des Menschen von der Informationsverarbeitung. Zwischenschritte sind akzeptabel, solange sie das Leben erleichtern. Aus diesem Grund gibt es Tools für die Zuordnung von Zwischeninformationen. Wie Codegeneratoren, Compiler, Transpiler usw.
Nehmen wir an, jemand bietet Ihnen eine solche Zuordnungsfunktion an, deren Implementierung für Sie unklar ist. Wenn die Funktion wie versprochen funktioniert, ist es Ihnen dann wichtig, ob intern Quellcode generiert wird oder nicht?
quelle
Insofern Sie später festlegen, dass es sich bei diesem Code um Daten handelt, reduziert sich Ihr Vorschlag auf "Wenn etwas generiert werden kann, ist das Ding kein Code." Würden Sie dann sagen, dass der von einem C-Compiler generierte Assembly-Code kein Code ist? Was passiert, wenn es genau mit dem Assembler-Code übereinstimmt, den ich von Hand schreibe? Du kannst gerne dorthin gehen, wenn du möchtest, aber ich werde nicht mit dir kommen.
Beginnen wir stattdessen mit einer Definition von "Code". Ohne zu technisch zu werden, wäre eine ziemlich gute Definition für die Zwecke dieser Diskussion "maschinell ausführbare Anweisungen zum Durchführen einer Berechnung".
Nun ja, Ihr Ausgangspunkt ist, dass Code nicht generiert werden kann, aber ich lehne diesen Vorschlag ab. Wenn Sie meine Definition von "Code" akzeptieren, sollte es im Allgemeinen kein konzeptionelles Problem bei der Codegenerierung geben.
Nun, das ist eine ganz andere Frage, nach dem Grund für die Codegenerierung und nicht nach ihrer Natur. Sie schlagen die Alternative vor, dass anstelle von Schreiben oder Verwenden eines Codegenerators eine Funktion geschrieben wird, die das Ergebnis direkt berechnet. Aber in welcher Sprache? Vorbei sind die Zeiten, in denen irgendjemand direkt in Maschinencode geschrieben hat. Wenn Sie Ihren Code in einer anderen Sprache schreiben, sind Sie auf einen Codegenerator in Form eines Compilers und / oder Assemblers angewiesen, um ein Programm zu erstellen, das tatsächlich ausgeführt wird.
Warum schreibst du dann lieber in Java oder C oder Lisp oder was auch immer? Auch Assembler? Ich behaupte, dass dies zumindest teilweise darauf zurückzuführen ist, dass diese Sprachen Abstraktionen für Daten und Operationen bereitstellen, die es einfacher machen, die Details der durchzuführenden Berechnung auszudrücken.
Gleiches gilt auch für die meisten übergeordneten Codegeneratoren. Die prototypischen Fälle sind wahrscheinlich Scanner- und Parser-Generatoren wie
lex
undyacc
. Ja, Sie können einen Scanner und einen Parser direkt in C oder in einer anderen Programmiersprache Ihrer Wahl schreiben (sogar in unformatiertem Maschinencode), und manchmal auch. Bei einem Problem mit erheblicher Komplexität erleichtert die Verwendung einer höheren Sprache für spezielle Zwecke wie Lex oder Yacc das Schreiben, Lesen und Verwalten des handgeschriebenen Codes. Meist auch viel kleiner.Sie sollten sich auch überlegen, was genau Sie unter "Codegenerator" verstehen. Ich würde C-Vorverarbeitung und die Instanziierung von C ++ - Vorlagen als Übung bei der Codegenerierung betrachten. lehnen Sie diese ab? Wenn nicht, dann müssen Sie einige mentale Gymnastik machen, um zu rationalisieren, dass Sie diese akzeptieren, aber andere Arten der Code-Generierung ablehnen.
Warum? Sie sind im Grunde genommen der Meinung, dass man ein universelles Programm haben sollte, in das der Benutzer Daten einspeist, von denen einige als "Anweisungen" und andere als "Eingaben" klassifiziert sind und das die Berechnung durchführt und mehr Daten ausgibt, die wir "Ausgaben" nennen. (Unter einem bestimmten Gesichtspunkt könnte man ein solches universelles Programm als "Betriebssystem" bezeichnen.) Aber warum sollte ein Compiler bei der Optimierung eines solchen universellen Programms genauso effektiv sein wie bei der Optimierung eines spezialisierteren Programm? Die beiden Programme haben unterschiedliche Eigenschaften und Fähigkeiten.
Sie sagen, dass eine universelle Schnittstellenbibliothek zwangsläufig eine gute Sache wäre. Vielleicht wäre es so, aber in vielen Fällen wäre eine solche Bibliothek groß und schwierig zu schreiben und zu warten, und vielleicht sogar langsam. Und wenn ein solches Tier tatsächlich nicht existiert, um das jeweilige Problem zu lösen, wer sind Sie dann, um darauf zu bestehen, dass eines erstellt wird, wenn ein Code-Generierungsansatz das Problem viel schneller und einfacher lösen kann?
Mehrere Dinge, denke ich.
Codegeneratoren wandeln in einer Sprache geschriebenen Code in Code in einer anderen, normalerweise niedrigeren Sprache um. Sie fragen sich also, warum die Leute Programme in mehreren Sprachen schreiben möchten und vor allem, warum sie möglicherweise Sprachen mit subjektiv unterschiedlichen Niveaus mischen möchten.
Aber das habe ich schon angesprochen. Man wählt eine Sprache für eine bestimmte Aufgabe zum Teil aufgrund ihrer Klarheit und Aussagekraft für diese Aufgabe. Da kleinerer Code im Durchschnitt weniger Fehler aufweist und einfacher zu warten ist, besteht zumindest bei umfangreichen Arbeiten eine Tendenz zu höheren Sprachen. Ein komplexes Programm beinhaltet jedoch viele Aufgaben, von denen einige in einer Sprache effektiver behandelt werden können, während andere in einer anderen Sprache effektiver oder prägnanter behandelt werden. Das richtige Werkzeug für den Job zu verwenden, bedeutet manchmal, Code zu generieren.
quelle
Beantwortung der Frage im Rahmen Ihres Kommentars:
Ein Compiler wird niemals für Ihre Aufgabe optimiert. Der Grund dafür ist einfach: Es ist für viele Aufgaben optimiert . Es ist ein Allzweckwerkzeug, das von vielen Menschen für viele verschiedene Aufgaben verwendet wird. Sobald Sie wissen, was Ihre Aufgabe ist, können Sie sich domänenspezifisch dem Code nähern und Kompromisse eingehen, die die Compiler nicht eingehen konnten.
Als Beispiel habe ich an Software gearbeitet, bei der ein Analyst möglicherweise Code schreiben muss. Sie könnten ihren Algorithmus in C ++ schreiben und alle Schrankenprüfungen und Memo-Tricks hinzufügen, von denen sie abhängen, aber das erfordert viel Wissen über die innere Funktionsweise des Codes. Sie schreiben lieber etwas Einfaches und lassen mich einen Algorithmus darauf anwenden, um den endgültigen C ++ - Code zu generieren. Dann kann ich exotische Tricks ausführen, um die Leistung zu maximieren, wie z. B. statische Analysen, von denen ich niemals erwarten würde, dass sie meine Analysten aushalten. Mithilfe der Codegenerierung können sie domänenspezifisch schreiben, wodurch sie das Produkt einfacher als jedes andere Allzweckwerkzeug auf den Markt bringen können.
Ich habe auch genau das Gegenteil getan. Ich habe eine weitere Arbeit, die das Mandat "Keine Code-Generierung" hatte. Wir wollten denen, die die Software verwenden, immer noch das Leben erleichtern, deshalb haben wir eine Menge Template-Metaprogramme verwendet, um den Compiler den Code im laufenden Betrieb generieren zu lassen. Daher brauchte ich nur die Allzwecksprache C ++, um meine Arbeit zu erledigen.
Es gibt jedoch einen Haken. Es war äußerst schwierig zu garantieren, dass die Fehler lesbar waren. Wenn Sie jemals metaprogrammierten Code für Vorlagen verwendet haben, wissen Sie, dass ein einzelner unschuldiger Fehler einen Fehler erzeugen kann, der 100 Zeilen mit unverständlichen Klassennamen und Vorlagenargumenten benötigt, um zu verstehen, was schief gelaufen ist. Dieser Effekt war so ausgeprägt, dass der empfohlene Debug-Vorgang für Syntaxfehler lautete: "Scrollen Sie durch das Fehlerprotokoll, bis Sie das erste Mal sehen, dass eine Ihrer eigenen Dateien einen Fehler aufweist. Wechseln Sie zu dieser Zeile und blinzeln Sie, bis Sie erkennen, was Sie tun falsch gemacht."
Wenn wir die Codegenerierung verwendet hätten, hätten wir viel leistungsfähigere Fehlerbehandlungsfunktionen mit vom Menschen lesbaren Fehlern. So ist das Leben.
quelle
Es gibt verschiedene Möglichkeiten, Code zu generieren. Sie könnten in drei Hauptgruppen eingeteilt werden:
Ich denke, Sie sprechen von der dritten Art des generierten Codes, da dies die umstrittenste Form ist. In den ersten beiden Formen ist der generierte Code ein Zwischenschritt, der sehr sauber vom Quellcode getrennt ist. In der dritten Form gibt es jedoch keine formale Trennung zwischen Quellcode und generiertem Code, außer dass der generierte Code wahrscheinlich einen Kommentar enthält, der besagt, dass "Diesen Code nicht bearbeiten". Es besteht immer noch das Risiko, dass Entwickler den generierten Code bearbeiten, was wirklich hässlich wäre. Aus Sicht des Compilers ist der generierte Code Quellcode.
Trotzdem können solche Formen des generierten Codes in einer statisch typisierten Sprache wirklich nützlich sein. Bei der Integration mit ORM-Entitäten ist es beispielsweise sehr nützlich, stark typisierte Wrapper für die Datenbanktabellen zu haben. Sicher, Sie könnten die Integration zur Laufzeit dynamisch handhaben, verlieren jedoch die Typensicherheit und die Toolunterstützung (Code-Vervollständigung). Ein Hauptvorteil der statischen Typensprache ist die Unterstützung des Typensystems bei der Art des Schreibens und nicht nur zur Laufzeit. (Umgekehrt ist diese Art der Codegenerierung in dynamisch typisierten Sprachen nicht sehr verbreitet, da sie in einer solchen Sprache im Vergleich zu Laufzeitkonvertierungen keinen Vorteil bietet.)
Da Typensicherheit und Code-Vervollständigung Funktionen sind, die Sie zur Kompilierungszeit (und beim Schreiben von Code in einer IDE) benötigen, werden reguläre Funktionen jedoch nur zur Laufzeit ausgeführt.
Es kann jedoch einen Mittelweg geben: F # unterstützt das Konzept von Typanbietern, bei dem es sich im Grunde um stark typisierte Schnittstellen handelt, die zur Kompilierungszeit programmgesteuert generiert werden. Dieses Konzept könnte wahrscheinlich viele Verwendungen der Codegenerierung ersetzen und eine sauberere Trennung von Bedenken ermöglichen.
quelle
Prozessorbefehlssätze sind grundsätzlich unerlässlich , aber Programmiersprachen können deklarativ sein . Das Ausführen eines Programms, das in einer deklarativen Sprache geschrieben ist, erfordert zwangsläufig eine Art Codegenerierung. Wie bereits in dieser und anderen Antworten erwähnt , besteht ein Hauptgrund für die Generierung von Quellcode in einer für Menschen lesbaren Sprache darin, die von Compilern durchgeführten raffinierten Optimierungen zu nutzen.
quelle
Sie haben es falsch herum verstanden. Es sollte lesen
Wenn etwas in einen Generator für interpretierbare Daten eingespeist werden kann , dann ist das Code, nicht Daten.
Es ist das Quellformat für diese Kompilierungsphase, und das Senkenformat ist immer noch Code.
quelle
gcc -fverbose-asm -O -S
ist kein Quellcode (und ist nicht nur oder größtenteils Daten), auch wenn es sich um eine Textform handelt, die immer an GNU weitergeleitetas
und manchmal von Menschen gelesen wird.