Widziałem, że jestem często progn
używany podczas przeglądania plików konfiguracyjnych doświadczonych użytkowników Emacsa. Znalazłem to miłe wytłumaczenieprogn
, ale naprawdę jestem ciekawy, jaka jest korzyść z używania tej funkcji? Weźmy na przykład ten fragment kodu (wzięty z konfiguracji Sacha Chua ):
(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)))
Czy jest jakaś istotna różnica między powyższą konfiguracją a tym?
(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))
Wydaje mi się, że pierwszy przykład jest w jakiś sposób bardziej przejrzysty, mimo że ma więcej składni, a moją intuicją jest to, że może zaistnieć pewien wzrost wydajności progn
, ale nie jestem pewien. Dziękujemy za wszelkie spostrzeżenia!
use-package
zawinieprogn
wokół twoich: config formularzy, jeśli go brakuje. Wypróbuj: możesz umieścić punkt na końcu a(use-package ...)
i wywołać,M-x pp-macroexpand-last-sexp
aby zobaczyć, jak makro jest rozwijane. Zobaczysz, że jest identyczny dla tych dwóch przykładów.progn
jest potrzebny: emacs.stackexchange.com/questions/39172/…Odpowiedzi:
progn
jest zwykle używany w przypadku makr. Niektóre makra (use-package
to makro, ostatnio sprawdzone) akceptują tylko 1 formularz , podczas gdy inne używają wszystkich pozostałych formularzy .progn
jest używany w pierwszym przypadku do przekształcenia sekwencji formularzy w jedną formę.W twoich przykładach pierwszy używa,
progn
a zatem jest 1 forma po:config
. W drugim są 3 formy . Jeśliuse-package
makro oczekuje tylko 1 formularza:config
, spowoduje błąd.Warto zauważyć, że użycie
progn
działa w obu przypadkach, pomijając to działa tylko wtedy, gdy makro akceptuje wiele formularzy. W rezultacie niektóre osoby wolą po prostu zawsze używaćprogn
, ponieważ zawsze będzie działać.źródło
progn
”, co oznacza, że akceptują dowolną liczbę sexps jako osobne argumenty i oceniają je kolejno. Inni nie, a zamiast tego oczekują / dopuszczają tylko jeden argument, w którym możesz chcieć oceniać wiele sexps po kolei. To wszystkoprogn
: pozwala ci podać pojedynczy sexp, który po ocenie oceniaprogn
sekwencję w sekwencjach. Porównaj(if true (progn a b c))
z(when true a b c)
. W obu przypadkacha
,b
ic
są oceniane w kolejności.use-package
zezwala na wiele formularzy w:config
i:init
.progn
seksu, który zawiera wiele seksu, które są oceniane pod kątem ich skutków ubocznych, przed zwróceniem wyniku ostatniego z nich. To naprawdę nie ma nic wspólnego z makrami. Makra „jako przykład” są w porządku. Sprawianie wrażenia, któreprogn
istnieje w przypadku makr i że 99% jego użycia dotyczy makr, jest mylące, IMO.progn
polega na przerzuceniu sekwencji ocen na jedną płeć (aby dopasować się do danego oczekiwanego argumentu), a zatem na efektach ubocznych .progn
został wprowadzony w Lisp 1.5 (patrz sekcja Funkcja programu ) w 1962 roku, na długo przed dodaniem makr do Lisp. Celem jest sekwencyjna ocena wyrażeń pod kątem ich skutków ubocznych. 2. Zobacz,progn
jak sam Emacs przedstawiaprogn
się programistom Elisp. Zobaczzap-to-char
kod prostego przypadku użycia.progn
ma to nic wspólnego z makrami. Jego celem jest oczywiście „ przekazywanie wielu formularzy jako pojedynczej formy ” (twoich słów) - czy to do funkcji, makra czy specjalnego formularza, ale także do „ Eval BODY formuje się sekwencyjnie i zwraca wartość ostatniego ” (ciąg znaków doc ). Teraz jak zawsze (rzeczywiście „te dni”!). Oczywiście, uporządkowana ocena jest ważna tylko dla skutków ubocznych. Dany przypadek użycia (makro lub nie) może, ale nie musi mieć znaczenia kolejność oceny, ale to nie ma znaczenia. Emacs Lisp nie jest pod tym względem wyjątkowy.Najważniejszy powód prognozy opisano w pierwszym wierszu dokumentacji prognozy ( wyróżnienie dodane):
Uzupełnienie:
Bez prognozy sekwencja nie jest gwarantowana, szczególnie jeśli kolejne wyrażenia zależą od efektów ubocznych lub zwracanych wartości poprzednich wyrażeń. progn wymusza sekwencję wykonywania taką samą jak sekwencja tekstowa. Pomaga nie mylić wykonania z analizą. To zachowanie sięga podstaw struktur kontrolnych seplenienia i programowania funkcjonalnego. Oto fragment (podkreślenie dodane) z podręcznika Lisp :
Czy prognostyka poprawia wydajność?
Analiza składni, nie. Wykonanie, nr W najlepszym razie może się równać, ale nigdy nie magicznie zwiększyć wydajności.
Po progn wykorzystywane ?
źródło
if
), Ale normalna kolejność oceny (np. Formularze najwyższego poziomu, ciała funkcji itp.) Jest tekstowa. Oczywiście, do pewnego stopnia jest to domniemaneprogn
, ale zwykle nie jest to do czego używaszprogn
w swoim własnym kodzie.(elisp) Sequencing
który łączysz, mówi wszystko.Lepszym sposobem zrozumienia tego, co
progn
jest, jest porównanie go z rodziną:prog1
iprog2
.n
Lub1
lub2
część nazwy oznacza rachunku z listy, której wynikiem są Państwo zainteresowani. Innymi słowy,progn
zwróci wynik ostatniego zestawienia w nim zawarte, natomiastprog1
powróci pierwsza, a podobnaprog2
.Dziś ta funkcjonalność wydaje się nieco niewygodna, ponieważ uczymy się, że albo oczekujemy, że program zwróci się w ostatniej instrukcji, albo wyraźnie instruujemy, co zwrócić. W ten sposób
prog1
iprog2
są bardzo rzadko stosowane. Jeśli jednak o tym pomyślisz, ma to sens, a oto jak:Różne języki programowania używają różnych strategii do opisania swojej semantyki. Rodzina Lisp była ściśle związana z semantyką denotacyjną. Bez wchodzenia w szczegóły, tego rodzaju semantyka ma szczególne trudności z czymś, co znamy jako „stwierdzenia”, które nie są „wyrażeniami”. Znaczenia kodu są zwykle rozpatrywane w kategoriach kombinacji funkcji, podczas gdy „instrukcja”, której nie można nawet opisać jako funkcji (ponieważ niczego nie ocenia) jest trudna do opanowania. Ponieważ jednak Lisp dopuszcza skutki uboczne, czasami programista chciałby użyć wyrażenia bez używania jego wartości w taki sposób, aby nie wpływał na wyrażenie następujące po nim. I tu właśnie
progX
wchodzi rodzina.W językach podobnych do C funkcja ta jest czasami znana jako punkt sekwencji (tj.
;
I,
na przykład).progn
jest tak samo niezbędny dla języków podobnych do Lisp, jak i dla języków podobnych;
do C. Jest to podstawowa cecha języka, którego nie można łatwo zastąpić. Jednak w przeciwieństwie do języków w stylu C, Lisp ma tendencję do budowania abstrakcji syntaktycznych, całkowicie ukrywając składnię niższego poziomu. Być może dlatego nieprogn
używasz go tak często, ale jest to jeden z ważnych elementów budujących abstrakcje języka wyższego poziomu (makra).źródło