Wird die Unterstützung von Makros in einer Programmiersprache als schädlich angesehen?

8

Der erste Missbrauch, der mir in C einfällt, ist:

#define if while 

Gleichzeitig ist es bei richtiger Anwendung äußerst handlich und leistungsstark.

Ähnliches passiert mit Common Lisp-Makros.

Warum unterstützen nicht alle Programmiersprachen solche Makros und welche Alternativen gibt es?

Werden sie als schädlich angesehen?

OscarRyz
quelle
20
Messer sind gefährlich. Eine Alternative ist, Dinge mit Löffeln zu schneiden.
Matt Ellen
1
@Matt oder um gute Griffe bereitzustellen.
OscarRyz

Antworten:

15

Ich bin der Meinung, dass eine Sprache, wenn sie Makros enthält, ein gut geplanter und integraler Bestandteil der Sprache und nicht des Compilers sein sollte .

Das Makrosystem von Lisp ist beispielsweise eine sehr leistungsfähige integrierte Sprachfunktion und unterliegt allen Regeln und Vorschriften von Lisp.

Gegenbeispiel: Das C / C ++ - Makrosystem ist von der Sprache getrennt und in den Compiler integriert. Das Ergebnis ist, dass Sie nicht auf die Einschränkungen Ihrer Sprache beschränkt sind und ungültigen Code erstellen und sprachspezifische Schlüsselwörter neu definieren können.

Letztendlich gibt es mehrere Sprachen, die keine Makrofunktion haben - aber diese Schriften werden nicht so sehr übersehen. Es hängt alles davon ab, wie ausdrucksstark eine Sprache ist und ob sie alternative Ansätze zur Metaprogrammierung hat. Die Metaprogrammierung ist nur eine Möglichkeit, um sicherzustellen, dass X bei der Ausführung von X in der gesamten Anwendung auf dieselbe Weise ausgeführt wird.

Berin Loritsch
quelle
4
Schlimmer noch, der C-Präprozessor ist nicht einmal Teil des Compilers.
1
Was ist der Unterschied, den Sie hier zwischen "der Sprache" und "dem Compiler" ziehen wollen? Das Makrosystem von C ist im Sprachstandard definiert, die Makros von Lisp werden tatsächlich vom Lisp-Compiler erweitert, und jede Sprachimplementierung wird letztendlich vom Compiler und den Standardbibliotheken definiert. Daher ist der Ausdruck "von der Sprache getrennt und in den Compiler eingebaut" unsinnig. Vielleicht ist der Unterschied, nach dem Sie suchen, dass C-Makros im Compiler-Frontend und Lisp-Makros im Backend implementiert sind?
Mason Wheeler
Die Unterscheidung hat mit der Konsistenz der Sprache zu tun. Stellen Sie sich das so vor: Sie planen, in ein fremdes Land zu reisen, und Sie müssen lernen, Französisch zu sprechen, um Orte zu besuchen und Lebensmittel zu kaufen. Wenn Sie sich mit dem Zoll befassen, müssen Sie lieber auch Schwedisch lernen oder sich nur mit Französisch befassen. C-Precompiler-Makros unterscheiden sich sowohl syntaktisch als auch grammatikalisch von Standard C. Die kognitive Herausforderung besteht darin, herauszufinden, was diese andere Sprache mit Ihrem Standard-C-Programm tun wird. In einigen Fällen ist es einfach, aber ich habe ganze Codephrasen als Makrodefinition gesehen. Jetzt debuggen Sie es.
Berin Loritsch
8

C-Makros und Lisp-Makros sind völlig unterschiedlich. C-Makros werden durch Ersetzen von Zeichenfolgen erweitert, bevor eine andere Verarbeitung durchgeführt wird. Lisp-Makros werden erweitert, nachdem der Eingabetext in einen Syntaxbaum 1 analysiert wurde , und können während der Erweiterung die gesamte Sprache verwenden. Mit Lisp-Makros können Sie nicht nur dumme Dinge tun #define begin {, sondern auch Ihre eigenen Kontrollstrukturen definieren und sogar Arrays zur Kompilierungszeit mit beliebigem Code füllen.

Ein Grund für das Nichteinschließen von Makros ist, dass es in Sprachen mit C-Syntax sehr schwierig sein kann, mit etwas Komplizierterem als dem einfachen Ersetzen von Zeichenfolgen zu arbeiten. Eine weitere Beschwerde über Makros ist, dass sie das Lesen von Code erschweren können. Dies kann zutreffen, wenn sie nicht geschickt implementiert werden. Gut geschriebene Lisp-Makros können das Lesen des Codes erleichtern.

1 mit Ausnahme von Lesemakros, die beim Erstellen des Syntaxbaums erweitert werden.

Larry Coleman
quelle
2

Ich glaube nicht, dass es einen bestimmten Grund gibt, warum sie in einigen Sprachen nicht unterstützt werden, genauso wie einige bei Groß- und Kleinschreibung unterscheiden und andere nicht. Normalerweise kein wirklicher Grund, nur eine Entscheidung, die getroffen wurde.

ABER der Grund, warum sie nicht enthalten sind, ist definitiv nicht die Sicherheit. Das

#define X Y

Die Anweisung ändert alle X in Ys zur Kompilierungszeit. Wenn Sie die # define-Anweisungen ändern können, können Sie einfach die Quelle, die Sie ändern möchten, kopieren / ersetzen und erneut kompilieren.

Mike M.
quelle