Wie weit können LISP-Makros gehen?

Translate

Ich habe viel gelesen, dass LISP die Syntax im laufenden Betrieb neu definieren kann, vermutlich mit Makros. Ich bin gespannt, wie weit das eigentlich geht? Können Sie die Sprachstruktur so stark neu definieren, dass sie grenzwertig zum Compiler für eine andere Sprache wird? Könnten Sie beispielsweise die Funktionsweise von LISP in eine objektorientiertere Syntax und Semantik ändern, beispielsweise eine Syntax, die näher an Ruby liegt?

Ist es insbesondere möglich, die Klammer-Hölle mit Makros loszuwerden? Ich habe genug (Emacs-) LISP gelernt, um Emacs mit meinen eigenen Mikrofunktionen anzupassen, aber ich bin sehr gespannt, wie weit Makros beim Anpassen der Sprache gehen können.

This question and all comments follow the "Attribution Required."

Alle Antworten

Translate

Das ist eine wirklich gute Frage.

Ich denke, es ist nuanciert, aber definitiv verantwortlich:

Makros stecken nicht in S-Ausdrücken. Im LOOP-Makro finden Sie eine sehr komplexe Sprache, die mit Schlüsselwörtern (Symbolen) geschrieben wurde. Während Sie die Schleife mit Klammern beginnen und beenden können, hat sie eine eigene Syntax.

Beispiel:

(loop for x from 0 below 100
      when (even x)
      collect x)

Davon abgesehen verwenden die meisten einfachen Makros nur S-Ausdrücke. Und Sie würden mit ihnen "stecken bleiben".

Aber S-Ausdrücke, wie Sergio geantwortet hat, fühlen sich richtig an. Die Syntax wird aus dem Weg geräumt und Sie beginnen mit der Codierung im Syntaxbaum.

Was Lesermakros betrifft, könnten Sie möglicherweise so etwas schreiben:

#R{
      ruby.code.goes.here
  }

Sie müssen jedoch Ihren eigenen Ruby-Syntaxparser schreiben.

Sie können auch einige der Ruby-Konstrukte wie Blöcke mit Makros nachahmen, die mit den vorhandenen Lisp-Konstrukten kompiliert werden.

#B(some lisp (code goes here))

würde übersetzen

(lambda () (some lisp (code goes here)))

Sehendiese Seitefür wie es geht.

Quelle
Translate

Ja, Sie können die Syntax neu definieren, sodass Lisp zum Compiler wird. Sie tun dies mit "Reader-Makros", die sich von den normalen "Compiler-Makros" unterscheiden, an die Sie wahrscheinlich denken.

Common Lisp verfügt über die integrierte Funktion zum Definieren einer neuen Syntax für den Leser und Lesermakros, um diese Syntax zu verarbeiten. Diese Verarbeitung erfolgt zum Zeitpunkt des Lesens (vor dem Kompilieren oder Auswerten). Weitere Informationen zum Definieren von Lesermakros in Common Lisp finden Sie in der Common Lisp-Hyperspec - Sie sollten lesenCH. 2, "Syntax"undCH. 23, "Leser". (Ich glaube, Schema hat die gleiche Einrichtung, aber ich bin nicht so vertraut damit - siehe dieSchemaquellenfür dieArc-Programmiersprache).

Nehmen wir als einfaches Beispiel an, Sie möchten, dass Lisp geschweifte Klammern anstelle von Klammern verwendet. Dies erfordert ungefähr die folgenden Leserdefinitionen:

;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
  (declare (ignore inchar))
  (read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)

(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )

;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )

Du sagst Lisp, dass das {wie ein (und das} wie ein) ist. Dann erstellen Sie eine Funktion (lcurly-brace-reader), die der Leser aufruft, wenn er ein {sieht, und Sie verwendenset-macro-characterum diese Funktion dem {zuzuweisen. Dann sagst du Lisp, dass (und) wie [und] sind (dh keine sinnvolle Syntax).

Andere Dinge, die Sie tun könnten, sind zum Beispiel:Erstellen einer neuen Zeichenfolgensyntaxoder verwenden Sie [und], um die In-Fix-Notation einzuschließen und in S-Ausdrücke zu verarbeiten.

Sie können auch weit darüber hinausgehen und die gesamte Syntax mit Ihren eigenen Makrozeichen neu definieren, die Aktionen im Reader auslösen, sodass der Himmel wirklich die Grenze ist. Dies ist nur einer der Gründe dafürPaul GrahamundAndereSagen Sie immer wieder, dass Lisp eine gute Sprache ist, um einen Compiler zu schreiben.

Quelle
Translate

Ich bin kein Lisp-Experte, zum Teufel bin ich nicht einmal ein Lisp-Programmierer, aber nach einigem Experimentieren mit der Sprache kam ich zu dem Schluss, dass die Klammern nach einer Weile unsichtbar werden und Sie den Code als sehen du willst es sein. Sie achten mehr auf die syntaktischen Konstrukte, die Sie mit s-exprs und Makros erstellen, und weniger auf die lexikalische Form des Textes aus Listen und Klammern.

Dies gilt insbesondere dann, wenn Sie einen guten Editor verwenden, der beim Einrücken und Färben der Syntax hilft (versuchen Sie, die Klammer auf eine Farbe zu setzen, die dem Hintergrund sehr ähnlich ist).

Möglicherweise können Sie die Sprache nicht vollständig ersetzen und erhalten die Ruby-Syntax, benötigen sie jedoch nicht. Dank der Sprachflexibilität könnten Sie einen Dialekt haben, der sich anfühlt, als würden Sie dem 'Ruby-Programmierstil' folgen, wenn Sie möchten, was auch immer das für Sie bedeuten würde.

Ich weiß, dass dies nur eine empirische Beobachtung ist, aber ich glaube, ich hatte einen dieser Lisp-Erleuchtungsmomente, als ich dies erkannte.

Quelle
Translate

Immer wieder wollen Neulinge in Lisp "alle Klammern loswerden". Es dauert ein paar Wochen. Kein Projekt, das eine seriöse Allzweck-Programmiersyntax auf der Grundlage des üblichen S-Expression-Parsers erstellt, kommt jemals irgendwohin, da Programmierer immer das bevorzugen, was Sie derzeit als "Hölle in Klammern" empfinden. Es ist etwas gewöhnungsbedürftig, aber nicht viel! Sobald Sie sich daran gewöhnt haben und die Plastizität der Standardsyntax wirklich zu schätzen wissen, ist es wirklich beeindruckend, zu Sprachen zurückzukehren, in denen es nur einen Weg gibt, ein bestimmtes Programmierkonstrukt auszudrücken.

Trotzdem ist Lisp ein hervorragendes Substrat für die Erstellung domänenspezifischer Sprachen. Genauso gut, wenn nicht besser als XML.

Viel Glück!

Quelle
Translate

Die beste Erklärung für Lisp-Makros, die ich je gesehen habe, ist bei

https://www.youtube.com/watch?v=4NO83wZVT0A

Dies ist ein Video eines Vortrags von Peter Seibel, dem Autor von "Practical Common Lisp", dem besten Lisp-Lehrbuch, das es gibt.

Die Motivation für Lisp-Makros ist normalerweise schwer zu erklären, da sie in Situationen, die zu lang sind, um sie in einem einfachen Tutorial darzustellen, wirklich zur Geltung kommen. Peter hat ein großartiges Beispiel. Sie können es vollständig erfassen und Lisp-Makros werden gut und richtig verwendet.

Sie fragten: "Könnten Sie die funktionale Natur von LISP in eine objektorientiertere Syntax und Semantik ändern?" Die Antwort ist ja. Tatsächlich hatte Lisp ursprünglich überhaupt keine objektorientierte Programmierung, was nicht verwunderlich ist, da es Lisp schon lange vor der objektorientierten Programmierung gibt! Als wir 1978 zum ersten Mal von OOP erfuhren, konnten wir es einfach unter Verwendung von Makros zu Lisp hinzufügen. Schließlich wurde das Common Lisp Object System (CLOS) entwickelt, ein sehr leistungsfähiges objektorientiertes Programmiersystem, das sich elegant in Lisp einfügt. Das Ganze kann als Erweiterung geladen werden - nichts ist eingebaut! Es ist alles mit Makros gemacht.

Lisp verfügt über eine völlig andere Funktion, die als "Lesermakros" bezeichnet wird und zur Erweiterung der Oberflächensyntax der Sprache verwendet werden kann. Mit Reader-Makros können Sie Subsprachen mit C-ähnlicher oder Ruby-ähnlicher Syntax erstellen. Sie wandeln den Text intern in Lisp um. Diese werden von den meisten echten Lisp-Programmierern nicht häufig verwendet, hauptsächlich weil es schwierig ist, die interaktive Entwicklungsumgebung zu erweitern, um die neue Syntax zu verstehen. Beispielsweise würden Emacs-Einrückungsbefehle durch eine neue Syntax verwirrt. Wenn Sie jedoch voller Energie sind, ist Emacs auch erweiterbar, und Sie können es über Ihre neue lexikalische Syntax unterrichten.

Quelle
Translate

Regelmäßige Makros bearbeiten Listen von Objekten. Am häufigsten sind diese Objekte andere Listen (wodurch Bäume gebildet werden) und Symbole, aber sie können auch andere Objekte wie Zeichenfolgen, Hashtabellen, benutzerdefinierte Objekte usw. sein. Diese Strukturen werden aufgerufens-exps.

Wenn Sie also eine Quelldatei laden, analysiert Ihr Lisp-Compiler den Text und erstellt S-Exps. Makros arbeiten mit diesen. Dies funktioniert hervorragend und ist eine wunderbare Möglichkeit, die Sprache im Geiste von s-exps zu erweitern.

Darüber hinaus kann der oben genannte Analyseprozess durch "Lesermakros" erweitert werden, mit denen Sie die Art und Weise anpassen können, wie Ihr Compiler Text in S-Exps umwandelt. Ich schlage jedoch vor, dass Sie die Syntax von Lisp verwenden, anstatt sie in etwas anderes zu biegen.

Sie klingen etwas verwirrt, wenn Sie Lisps "funktionale Natur" und Rubys "objektorientierte Syntax" erwähnen. Ich bin nicht sicher, was "objektorientierte Syntax" sein soll, aber Lisp ist eine Multi-Paradigmen-Sprache und unterstützt objektorientierte ProgrammierungextremGut.

Übrigens, wenn ich Lisp sage, meine ichCommon Lisp.

Ich schlage vor, Sie beseitigen Ihre Vorurteile undGib Lisp einen ehrlichen Versuch.

Quelle
Translate

Klammer Hölle? Ich sehe keine Klammern mehr in:

(function toto)

als in:

function(toto);

Und in

(if tata (toto)
  (titi)
  (tutu))

nicht mehr als in:

if (tata)
  toto();
else
{
  titi();
  tutu();
}

Ich sehe weniger Klammern und ';' obwohl.

Quelle
Translate

Was Sie fragen, ist ein bisschen wie zu fragen, wie man ein erfahrener Chocolatier wird, damit Sie all das höllisch braune Zeug von Ihrem Lieblingsschokoladenkuchen entfernen können.

Quelle
HD.
Translate

Ja, Sie können die Syntax grundlegend ändern und sogar der "Hölle der Klammern" entkommen. Dazu müssen Sie eine neue Reader-Syntax definieren. Schauen Sie sich Lesermakros an.

Ich vermute jedoch, dass Sie, um das Niveau der Lisp-Expertise für die Programmierung solcher Makros zu erreichen, so weit in die Sprache eintauchen müssen, dass Sie die "Hölle" der Eltern nicht mehr in Betracht ziehen. Das heißt, wenn Sie wissen, wie Sie sie vermeiden können, werden Sie sie als eine gute Sache akzeptieren.

Quelle
Translate

Wenn Sie möchten, dass Lisp wie Ruby aussieht, verwenden Sie Ruby.

Es ist möglich, Ruby (und Python) sehr lispig zu verwenden, was einer der Hauptgründe ist, warum sie so schnell Akzeptanz gefunden haben.

Quelle
Translate

In diesem Beispiel sehen Sie, wie Reader-Makros den Lisp-Reader mit komplexen Aufgaben wie XML-Vorlagen erweitern können:

http://common-lisp.net/project/cl-quasi-quote/���z {rV���m�Xm

dieseBenutzerbibliothekKompiliert die statischen Teile des XML zur Kompilierungszeit in UTF-8-codierte Literalbyte-Arrays, die bereit sind, in den Netzwerkstrom geschrieben zu werden. und sie können in normalen Lisp-Makros verwendet werden, sie sind orthogonal ... Die Platzierung des Kommazeichens beeinflusst, welche Teile konstant sind und welche zur Laufzeit ausgewertet werden sollten.

Weitere Details finden Sie unter:http://common-lisp.net/project/cl-quasi-quote/

ein weiteres Projekt, das für Common Lisp-Syntaxerweiterungen:http://common-lisp.net/project/cl-syntax-sugar/

Quelle
Translate

@sparkes

Manchmal ist LISP die klare Sprachwahl, nämlich Emacs-Erweiterungen. Ich bin sicher, ich könnte Ruby verwenden, um Emacs zu erweitern, wenn ich wollte, aber Emacs wurde entwickelt, um mit LISP erweitert zu werden, daher scheint es sinnvoll, es in dieser Situation zu verwenden.

Quelle
Translate

Es ist eine schwierige Frage. Da lisp strukturell bereits so nahe an einem Analysebaum liegt, ist der Unterschied zwischen einer großen Anzahl von Makros und der Implementierung Ihrer eigenen Minisprache in einem Parsergenerator nicht sehr klar. Aber mit Ausnahme des öffnenden und schließenden Parens könnte es sehr leicht zu etwas kommen, das nicht nach Lisp aussieht.

Quelle
Translate

Eine der Anwendungen von Makros, die mich umgehauen haben, war die Überprüfung von SQL-Anforderungen zur DB zur Kompilierungszeit.

Sobald Sie feststellen, dass Sie zur Kompilierungszeit die vollständige Sprache zur Hand haben, eröffnen sich interessante neue Perspektiven. Dies bedeutet auch, dass Sie sich auf interessante neue Weise in den Fuß schießen können (z. B. wenn die Zusammenstellung nicht reproduzierbar ist, was sehr leicht zu einem Debugging-Albtraum werden kann).

Quelle