Progn'u ne zaman / neden kullanmalıyım?


19

prognDeneyimli Emacs kullanıcılarının yapılandırma dosyalarına göz atarken oldukça kullanıldığını gördüm . Bu güzel açıklamayıprogn buldum , ama gerçekten merak ettiğim şey, bu işlevi kullanmanın yararı nedir? Örneğin bu pasajı ( Sacha Chua'nın yapılandırmasından alınmıştır ) alın:

(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)))

Yukarıdaki yapılandırma ile bu arasında önemli bir fark var mı?

(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))

İlk örneğin daha fazla sözdizimi olmasına rağmen bir şekilde daha temiz olduğunu hissediyorum ve sezgim kullanmaktan bir tür performans artışı olabilir progn, ama emin değilim. Görüşleriniz için teşekkür ederiz!


7
Bu özel durumda bir fark yoktur: eksikse: config formlarınızın çevresini use-packagesarar progn. Deneyin: a'nın sonuna nokta koyabilir ve makronun nasıl genişletildiğini görmek için (use-package ...)çağrı yapabilirsiniz M-x pp-macroexpand-last-sexp. Bu iki örnek için aynı olduğunu göreceksiniz.
glucas

prognGerekli olan bir örnek : emacs.stackexchange.com/questions/39172/…
npostavs

Yanıtlar:


11

progngenellikle makrolarla uğraşırken kullanılır. Bazı makrolar ( use-packagebir makro, son kontrol ettiğim) sadece 1 formu kabul eder , diğerlerinde kalan tüm formları tüketir .

progn önceki durumda, bir form dizisini tek bir forma dönüştürmek için kullanılır.

Örneklerinizde, ilki kullanır prognve böylece 1 form sonra vardır :config. İkincisinde 3 form vardır . Eğer use-packagemakro yalnızca 1 formu aşağıdaki beklediğini :config, o zaman hataya neden olur.

Her progniki durumda da kullanmanın işe yaradığını belirtirken, yalnızca makro birden çok formu kabul ederse işe yaradığını belirtmek gerekir. Bunun bir sonucu olarak, bazı insanlar her zaman kullanmayı tercih ederler progn, çünkü her zaman işe yarayacaktır.


15
Gerçekten makrolarla hiçbir ilgisi yok. Bazı işlevler ve makrolar "örtük progn" olarak adlandırılırlar , yani herhangi bir sayıda sexps'i ayrı bağımsız değişken olarak kabul eder ve bunları sırayla değerlendirirler. Diğerleri, birden çok sexps'i sırayla değerlendirmek isteyebileceğiniz tek bir argümanı beklemez / buna izin vermez / izin vermez. Hepsi prognbu kadar: değerlendirildiğinde sexp argümanlarını prognsırayla değerlendiren tek bir sexp vermenizi sağlar . Karşılaştırma (if true (progn a b c))ile (when true a b c). Her iki durumda da, a, bve csırayla değerlendirilir.
Drew


4
Kullanım durumlarının% 99'unun makrolar için olduğunu kabul etmiyorum . Herhangi bir işlev veya makro , prognbunların sonuncusunun sonucunu döndürmeden önce, yan etkileri için değerlendirilen birden fazla sexps içeren bir sexp'den geçirilebilir . Gerçekten makrolarla hiçbir ilgisi yok. Makrolar "örnek olarak" iyidir. prognMakrolar için var olan ve kullanımının% 99'unun makrolar için olduğu izlenimini vermek yanıltıcıdır, IMO. prognbir dizi değerlendirmeyi tek bir cinsiyete (belirli bir beklenen argümanı sığdırmak için) küreklemekle ilgilidir ve bu nedenle yan etkilerle ilgilidir .
Drew

5
1. prognyılında tanıtıldı Lisp 1.5 (bölüm bkz Program Özelliği , 1962 yılında,) uzun makroları Lisp'te eklenmiştir önce. Amaç ifadeleri yan etkileri açısından sırayla değerlendirmektir. 2. Emacs'ın kendisinin Elisp programcılarına prognnasıl tanıtıldığını görün . Basit bir kullanım durumu için koda bakın . prognzap-to-char
Drew

2
Anlaşamadığımızı kabul edebiliriz. Benim demek ki prognvardır olursa olsun makrolar ile ilgisi. Amacı elbette " birden çok formu tek bir form olarak geçirmek " (kelimeleriniz) - ister bir fonksiyona, bir makroya ya da özel bir forma olsun, aynı zamanda " VÜCUT formlarını sırayla değerlendirin ve sonuncunun değerini döndürün " (doc string) ). Şimdi her zamanki gibi ("bugünler", gerçekten!). Düzenli bir değerlendirme, sadece yan etkiler için önemlidir. Belirli bir kullanım durumu (makro ya da değil) değerlendirme sırasını dikkate alabilir ya da umursamayabilir, ancak bu önemsizdir. Ve Emacs Lisp bu konuda hiçbir şekilde istisnai değildir.
Drew

10

Prognun en önemli nedeni progn belgelerinin ilk satırında açıklanmaktadır (vurgu eklenmiştir):

progn, bağımsız değişkenlerinin her birinin sırayla değerlendirilmesine neden olan ve sonra sonuncusunun değerini döndüren özel bir formdur .

Zeyilname:

Progn olmadan , özellikle sonraki ifadeler önceki ifadelerin yan etkilerine veya dönüş değerlerine bağlıysa , sekans garanti edilmez. progn yürütme sekansını metinsel sekansla aynı şekilde uygular. Yürütmeyi ayrıştırma ile karıştırmamaya yardımcı olur. Bu davranış lisp kontrol yapılarının ve fonksiyonel programlamanın temellerine dayanır. Lisp referans kılavuzundan bir alıntı (vurgu eklendi) :

Yerleşik kontrol yapıları özel formlardır çünkü alt formları mutlaka değerlendirilmez veya sırayla değerlendirilmez .

Progn performansı artırır mı ?

Ayrıştırma performansı, hayır. Yürütme performansı, hayır. En iyi ihtimalle performansı eşitleyebilir ancak sihirli bir şekilde arttıramaz.

Progn ne zaman kullanılır ?

... çoğu zaman bir iç -çözülme korumak ve ya veya bir sonra-kesiminde ise .


Bunun neden bu kadar önemli olduğundan emin değilim. Emacs her zaman sırayla değerlendirir.
lunaryorn

2
@lunaryorn güncellenmiş cevaba bakınız.
Emacs Kullanıcısı

Düzenlemenizi anladığımdan emin değilim. Doğal olarak, farklı bir değerlendirme sırasına (ör. if) Sahip özel formlar vardır , ancak normal değerlendirme sırası (örn. Üst düzey formlar, fonksiyon gövdeleri, vb.) Metinseldir. Elbette, bir dereceye kadar bu örtüktür progn, ancak genellikle progn kendi kodunuzda kullandığınız şey bu değildir .
lunaryorn

Sanırım bağladığınız Elisp manuel düğümü (elisp) Sequencingher şeyi söylüyor.
Fesleğen

10

Ne prognolduğunu anlamanın daha iyi bir yolu, onu aile ile karşılaştırmaktır: prog1ve prog2. nVeya 1veya 2adının bir parçası sonucu ilgilendiğiniz listeden açıklamada kısaltmasıdır. Bir başka deyişle, prognoysa, içerdiği son ifadenin sonucunu döndürür prog1ilk ve benzer dönecektir prog2.

Bugün bu işlevsellik biraz garip görünüyor çünkü programın son ifadede geri dönmesini beklemeyi ya da açıkça neyin geri döneceğini bildirmeyi öğreniyoruz. Böylece prog1ve prog2nadiren kullanılırlar. Ancak, bunu düşünürseniz, mantıklıdır ve işte şöyle:

Farklı programlama dilleri semantiklerini tanımlamak için farklı stratejiler kullanır. Lisp ailesi eskiden anlamsal semantiğe sıkı sıkıya bağlıydı. Çok fazla ayrıntıya girmeden, bu tür anlambilim "ifadeler" olarak bildiğimiz "ifadeler" olarak bildiğimiz bir şeyle ilgili özel bir güçlük çeker. Kodun anlamları genellikle işlev kombinasyonları açısından düşünülürken, işlev olarak bile tanımlanamayan bir "deyim" (hiçbir şeyi değerlendirmediği için) ile başa çıkmak zordur. Bununla birlikte, Lisp yan etkilere izin verdiğinden, bazen bir programcı bir ifadeyi değerini izleyen ifadeyi etkilemeyecek şekilde kullanmadan kullanmak ister. progXAilen burada devreye giriyor.

C benzeri dillerde bu özellik bazen sıralama noktası olarak bilinir (örneğin ;ve ,örneğin). prognLisp benzeri diller için ;olduğu kadar C benzeri diller için de gereklidir . Kolayca değiştirilemeyen dilin temel bir özelliğidir. Bununla birlikte, C tarzı dillerin aksine, Lisp, daha düşük seviyenin sözdizimini tamamen gizleyerek sözdizimsel soyutlamalar oluşturma eğilimindedir. Ve belki de prognbu kadar sık ​​kullandığınızı görmüyorsunuz , ancak daha üst düzey dil soyutlamaları (sa makroları) oluşturmak söz konusu olduğunda önemli yapı taşlarından biridir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.