いつ/なぜprognを使用する必要がありますか?


19

progn経験豊富なEmacsユーザーの構成ファイルを参照するときに、かなり頻繁に使用されるのを見てきました。のこの素晴らしい説明prognを見つけましたが、私が本当に興味を持っているのは、この関数を使用する利点は何ですか?たとえば、次のスニペット(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)))

上記の構成とこれに大きな違いはありますか?

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

最初の例はより構文が多いにも関わらず、よりクリーンであるように感じます。また、私の直感では、を使用することで何らかのパフォーマンスの向上があるかもしれませんがprogn、よくわかりません。洞察力をありがとう!


7
この特定のケースでは違いはありません::configフォームがない場合use-packageはラップprognします。試してみてください:aの最後にポイントを置いて(use-package ...)呼び出しM-x pp-macroexpand-last-sexpて、マクロがどのように展開されるかを確認できます。これらの2つの例で同じであることがわかります。
グルーカス

例えば、progn必要とされている:emacs.stackexchange.com/questions/39172/...は
npostavs

回答:


11

progn通常、マクロを扱うときに使用されます。いくつかのマクロ(use-packageマクロ、最後に私がチェックされている)を受け入れるだけ1 フォーム他の人が消費し、残りのすべてのフォームを

progn 前者の場合、一連のフォームを単一のフォームに変換するために使用されます。

お使いの例では、最初の1つの用途prognとは、このようにそこにある1つのフォームの後:config。2番目には、3つの形式があります。use-packageマクロが次の1つの形式のみを想定している場合、:configエラーが発生します。

prognどちらの場合でも使用することは機能しますが、省略すると、マクロが複数のフォームを受け入れる場合にのみ機能することに注意してください。この結果、一部の人々は常に使用することを好むため、常に使用することを好みprognます。


15
マクロとはまったく関係ありません。一部の関数とマクロには、いわゆる「暗黙のprogn」があります。これは、任意の数のsexpを個別の引数として受け入れ、それらを順番に評価することを意味します。他の人はそうではなく、代わりに複数のsexpsを連続して評価したいかもしれない単一の引数のみを期待/許可します。それはすべてprognです:評価されると、sexp argsをprogn順番に評価する単一のsexpを提供できます。と比較(if true (progn a b c))してください(when true a b c)。どちらの場合も、ab、とc順番に評価されています。
ドリュー


4
使用例の99%がマクロなどに使用されることに同意しません。関数またはマクロprogn、副作用の評価が行われる複数のsexpを含むsexp に渡されてから、最後の結果を返すことができます。マクロとはまったく関係ありません。「例として」のマクロは問題ありません。prognマクロに存在し、その使用の99%がマクロに使用されているという印象を与えることは、紛らわしいです、IMO。prognは、一連の評価を単一の sexpにシャベル化すること(特定の予想される引数に適合するため)であり、したがって、副作用に関するものです。
ドリュー

5
1. マクロがLispに追加されるずっと前の1962年に、Lisp 1.5でprogn導入されました(セクションプログラム機能を参照)。その目的は、式の副作用を順次評価することです。2. Emacs自体がElispプログラマにどのように導入されているかを確認してください。簡単な使用例については、コードを参照してください。prognprognzap-to-char
ドリュー

2
私たちは同意しないことに同意することができます。私のポイントは、マクロprogn何の関係もないということです。その目的は、もちろん、「複数のフォームを単一のフォームとして渡す」(あなたの言葉)-関数、マクロ、または特別なフォームのいずれかですが、「Eval BODYフォームを順番に返し、最後の値を返す」(doc string )。、相変わらず(「これらの日」、確かに!)。明らかに、順序付けられた評価は副作用に対してのみ重要です。特定のユースケース(マクロかどうか)は、評価の順序を考慮する場合としない場合がありますが、それは無関係です。また、Emacs Lispはこの点で決して例外ではありません。
ドリュー

10

prognの最も重要な理由は、prognドキュメントの最初の行で説明されています(強調が追加されています)。

prognは、各引数を順番に評価し、最後の引数の値を返す特別な形式です。

補遺:

なしでのprogn、シーケンスは、後続の式は、前の式の副作用や戻り値に依存している場合は特に、保証するものではありません。prognは、テキストシーケンスと同じ実行シーケンスを実行します。実行と解析を混同しないようにします。この振る舞いは、Lisp制御構造と関数型プログラミングの基礎に戻ります。以下は、lispリファレンスマニュアルからの抜粋(強調を追加)です。

組み込み制御構造は、サブフォームが必ずしも評価されない、連続して評価されないため、特別な形式です。

prognパフォーマンスを向上させますか?

解析パフォーマンス、いいえ。実行パフォーマンス、いいえ。せいぜい同等ですが、魔法のようにパフォーマンスを向上させることはありません。

ときにされてのprognを 使用しますか

...ほとんどの場合、unwind-protect、and、or、またはifの then-part内。


なぜそんなに重要なのかはわかりません。Emacsは常に順番に評価します。
lunaryorn

2
@lunaryornは更新された回答を参照してください。
Emacsユーザー

あなたの編集を理解しているかどうかわかりません。当然、異なる評価順序(例:)を持つ特別な形式がありますifが、通常の評価順序(例:トップレベルフォーム、関数本体など)はテキスト形式です。確かに、ある程度は暗黙的prognですが、通常はprogn 自分のコードで使用するものではありません。
lunaryorn

(elisp) SequencingリンクしているElispの手動ノードがすべてを言っていると思います。
バジル

10

prognそれを家族と比較することで、それが何であるかを理解するより良い方法がprog1ありprog2ます。名前のnor 1または2一部は、結果に関心のあるリストのステートメントを表します。つまり、progn含まれる最後のステートメントの結果をprog1返しますが、最初の、および同様のステートメントを返しprog2ます。

今日、プログラムが最後のステートメントで戻ることを期待するか、何を返すかを明示的に指示することを学ぶため、この機能は少し厄介に思えます。したがってprog1prog2使用されることはほとんどありません。ただし、それについて考える場合、それは理にかなっており、ここに方法があります:

異なるプログラミング言語は、異なる戦略を使用してセマンティクスを記述します。Lispファミリは、表示の意味論と密接に結びついていました。詳細に説明しなくても、この種のセマンティクスには、「式」ではなく「ステートメント」として知られるようになったものに特に困難があります。通常、コードの意味は関数の組み合わせの観点から考えられますが、関数としても記述できない「ステートメント」(何にも評価されないため)を扱うのは困難です。しかし、Lispは副作用を許可するため、プログラマーは、値を使用せずに、その後の式に影響を与えない方法で式を使用したい場合があります。そして、ここがprogX家族の出番です。

C-ような言語では、この機能は、時にはとして知られている配列の点(すなわち、;および,例えば)。 prognLispライクな言語にとって、;Cライクな言語と同様に不可欠です。これは、簡単に置き換えることのできない言語の基本的な機能です。しかし、Cスタイルの言語とは異なり、Lispは低レベルの構文を完全に隠すことにより、構文の抽象化を構築する傾向があります。そして、これはおそらくあなたがそれほどprogn頻繁に使用されるのを見ない理由ですが、それはより高いレベルの言語抽象化(マクロ)を構築することになると、重要なビルディングブロックの1つです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.