Beim progn
Durchsuchen der Konfigurationsdateien erfahrener Emacs-Benutzer wurde ich häufig verwendet. Ich fand diese nette Erklärung vonprogn
, aber was mich wirklich interessiert ist, was ist der Vorteil der Verwendung dieser Funktion? Nehmen Sie zum Beispiel diesen Ausschnitt (entnommen aus Sacha Chuas Konfiguration ):
(use-package undo-tree
:defer t
:ensure t
:diminish undo-tree-mode
:config
(progn
(global-undo-tree-mode)
(setq undo-tree-visualizer-timestamps t)
(setq undo-tree-visualizer-diff t)))
Gibt es einen großen Unterschied zwischen der obigen Konfiguration und dieser?
(use-package undo-tree
:defer t
:ensure t
:diminish undo-tree-mode
:config
(global-undo-tree-mode)
(setq undo-tree-visualizer-timestamps t)
(setq undo-tree-visualizer-diff t))
Ich denke, das erste Beispiel ist irgendwie sauberer, obwohl es mehr Syntax hat, und meine Intuition ist, dass es eine Art Leistungssteigerung durch die Verwendung geben könnte progn
, aber ich bin nicht sicher. Vielen Dank für eventuelle Einblicke!
use-package
Wirdprogn
Ihre: config-Formulare umschließen, wenn sie fehlen. Probieren Sie es aus: Sie können einen Punkt am Ende von a setzen(use-package ...)
und aufrufen, umM-x pp-macroexpand-last-sexp
zu sehen, wie das Makro erweitert wird. Sie werden sehen, dass es für diese beiden Beispiele identisch ist.progn
es gebraucht wird: emacs.stackexchange.com/questions/39172/…Antworten:
progn
wird normalerweise beim Umgang mit Makros verwendet. Einige Makros (use-package
ein Makro, das ich zuletzt überprüft habe) akzeptieren nur ein Formular , während andere alle verbleibenden Formulare verwenden .progn
wird im ersteren Fall verwendet, um eine Folge von Formularen in ein einziges Formular umzuwandeln.In Ihren Beispielen wird das erste verwendet
progn
und daher gibt es 1 Formular danach:config
. Im zweiten gibt es 3 Formen . Wenn dasuse-package
Makro nur 1 folgende Form erwartet:config
, verursacht es einen Fehler.Es ist erwähnenswert, dass die Verwendung
progn
in beiden Fällen funktioniert, während das Weglassen nur funktioniert, wenn das Makro mehrere Formen akzeptiert. Infolgedessen bevorzugen einige Leute einfach immer zu verwendenprogn
, weil es immer funktionieren wird.quelle
progn
", dh sie akzeptieren eine beliebige Anzahl von Sexps als separate Argumente und werten sie nacheinander aus. Andere tun dies nicht und erwarten / erlauben stattdessen nur ein einziges Argument, bei dem Sie mehrere Sexps nacheinander bewerten möchten. Das ist allesprogn
: Sie können ein einzelnes sexp bereitstellen, das bei der Auswertung die sexp-Argumente nacheinander auswertetprogn
. Vergleichen Sie(if true (progn a b c))
mit(when true a b c)
. In beiden Fällen werdena
,b
und derc
Reihe nach ausgewertet.use-package
erlaubt mehrere Formen in:config
und:init
.progn
Sexp übergeben werden, der mehrere Sexps enthält, die auf ihre Nebenwirkungen hin untersucht werden, bevor das Ergebnis des letzten davon zurückgegeben wird. Es hat wirklich nichts mit Makros zu tun. Makros "als Beispiel" sind in Ordnung. Esprogn
ist irreführend, den Eindruck zu erwecken, dass Makros existieren und zu 99% für Makros verwendet werden.progn
Es geht darum, eine Sequenz von Bewertungen in ein einziges Geschlecht zu schaufeln (um zu einem gegebenen erwarteten Argument zu passen), und es geht daher um Nebenwirkungen .progn
wurde 1962 in Lisp 1.5 eingeführt (siehe Abschnitt Das Programmfeature ), lange bevor Makros zu Lisp hinzugefügt wurden. Der Zweck besteht darin, Ausdrücke nacheinander auf ihre Nebenwirkungen zu untersuchen. 2. Sieheprogn
, wie Emacs selbst führtprogn
zu Elisp Programmierer. Siehe denzap-to-char
Code für einen einfachen Anwendungsfall.progn
das überhaupt nichts mit Makros zu tun hat. Ihr Zweck ist es natürlich, " mehrere Formulare als ein einziges Formular zu übergeben " (Ihre Wörter) - ob an eine Funktion oder ein Makro oder ein spezielles Formular, aber auch an " BODY-Formulare nacheinander auswerten und den Wert des letzten zurückgeben " (doc string) ). Jetzt wie immer ("in diesen Tagen" tatsächlich!). Eine geordnete Bewertung ist natürlich nur für Nebenwirkungen wichtig. Ein gegebener Anwendungsfall (Makro oder nicht) kümmert sich möglicherweise nicht um die Auswertungsreihenfolge, aber das ist irrelevant. Und Emacs Lisp ist in dieser Hinsicht in keiner Weise außergewöhnlich.Der wichtigste Grund für die Prognose wird in der ersten Zeile der Prognosedokumentation beschrieben (Hervorhebung hinzugefügt):
Nachtrag:
Ohne Prognose kann die Reihenfolge nicht garantiert werden, insbesondere wenn nachfolgende Ausdrücke von den Nebenwirkungen oder Rückgabewerten der vorherigen Ausdrücke abhängen. progn erzwingt die Ausführungsreihenfolge genauso wie die Textreihenfolge . Hilft, die Ausführung nicht mit dem Parsen zu verwechseln. Dieses Verhalten geht auf die Grundlagen von Lisp-Kontrollstrukturen und funktionaler Programmierung zurück. Hier ist ein Auszug (Hervorhebung hinzugefügt) aus dem Lisp-Referenzhandbuch :
Hat progn Leistung zu steigern?
Parsing-Leistung, nein. Ausführungsleistung, nein. Bestenfalls kann es gleich sein, aber niemals die Leistung auf magische Weise steigern.
Wann wird progn verwendet ?
quelle
if
), aber die normale Bewertungsreihenfolge (z. B. Formulare der obersten Ebene, Funktionskörper usw.) ist textuell. Sicher, bis zu einem gewissen Grad ist das implizitprogn
, aber normalerweise verwenden Sie das nichtprogn
für Ihren eigenen Code.(elisp) Sequencing
den Sie verknüpfen, sagt schon alles.Ein besserer Weg, um zu verstehen, was
progn
ist, besteht darin, es mit der Familie zu vergleichen:prog1
undprog2
. Dasn
oder1
oder ein2
Teil des Namens steht für die Anweisung aus der Liste, deren Ergebnis Sie interessiert. Mit anderen Worten,progn
gibt das Ergebnis der letzten Anweisung zurück, währendprog1
die erste und ähnliche zurückgegeben wirdprog2
.Heutzutage scheint diese Funktionalität etwas umständlich zu sein, da wir lernen, entweder zu erwarten, dass das Programm in der letzten Anweisung zurückkehrt, oder es explizit anzuweisen, was zurückgegeben werden soll. Daher
prog1
undprog2
werden sehr selten verwendet. Wenn Sie jedoch darüber nachdenken, ist es sinnvoll, und hier ist, wie:Verschiedene Programmiersprachen verwenden unterschiedliche Strategien, um ihre Semantik zu beschreiben. Die Familie Lisp war eng mit der Denotationssemantik verbunden. Ohne ins Detail zu gehen, hat diese Art von Semantik besondere Schwierigkeiten mit etwas, das wir als "Aussagen" kennengelernt haben, die keine "Ausdrücke" sind. Codebedeutungen werden typischerweise in Form von Funktionskombinationen gedacht, während eine "Anweisung", die nicht einmal als Funktion beschrieben werden kann (da sie nichts wertet), daher schwierig zu behandeln ist. Da Lisp jedoch Nebenwirkungen zulässt, möchte ein Programmierer manchmal einen Ausdruck verwenden, ohne seinen Wert so zu verwenden, dass er den darauf folgenden Ausdruck nicht beeinflusst. Und hier kommt die
progX
Familie ins Spiel.In C-ähnlichen Sprachen ist diese Funktion manchmal als Sequenzpunkt (dh
;
und,
zum Beispiel).progn
ist für Lisp-ähnliche Sprachen genauso wichtig wie;
für C-ähnliche Sprachen. Es ist ein grundlegendes Merkmal der Sprache, das man nicht einfach ersetzen kann. Im Gegensatz zu C-Sprachen tendiert Lisp jedoch dazu, syntaktische Abstraktionen zu erstellen, indem die Syntax der unteren Ebene vollständig ausgeblendet wird. Und das ist vielleicht der Grund, warum man es nicht soprogn
oft benutzt sieht , aber es ist einer der wichtigen Bausteine, wenn es darum geht, übergeordnete Sprachabstraktionen (sa-Makros) zu erstellen.quelle