ラムダ式をシャープクォートするのはいつですか?


30

Q:今までならば、それはに便利ですときに、シャープ引用lambdaし、これまでならばとき、私たちがしなければならないではないシャープ引用lambda

人々lambdaは3つの方法でsを使用します。

  1. 平野: (lambda (x) x)
  2. 引用: '(lambda (x) x)
  3. シャープ引用符: #'(lambda (x) x)

このSOスレッドが三種類を説明し、このSOスレッドはなぜ引用符(NB:しないように説明してシャープ引用符lambdaだ、とこのSOスレッドはまた、引用符とシャープクォート間の区別を説明します。

ここで、匿名関数の手動ノードlambdalambdasが自己引用符であることに注意するためのdocstring :

フォームの呼び出し(lambda ARGS DOCSTRING INTERACTIVE BODY)は自己引用です。ラムダ式を評価した結果は式そのものです。ラムダ式は関数として扱われます...

そのため、(lambda (x) x)#'(lambda (x) x)は同等であるように見えますが、そうで'(lambda (x) x)はありません(最も重要なことは、バイトコンパイル時)。

a を引用することはめったにないように見えますlambdaが、シャープ引用符を使用する必要があるかどうかは不明です。

  • シャープクォートはlambda単なるスタイル上の選択ですか、それともシャープクォートが実際に役立つ状況はありますか?
  • aをクォートクォートしてはいけないlambda、つまりそうするとコードの意味が変わるような状況はありますか?

回答:


28

むかしむかし、ラムダには鋭い引用が必要でしたが、今ではそうではありません。

したがって、(lambda(x)x)と# '(lambda(x)x)は同等ですが、'(lambda(x)x)はそうではありません(最も重要なことは、バイトコンパイル時)。

はい。実際、最初の2つは評価時に完全に同一です。リンクしたマニュアルページで説明されているように:

次の形式はすべて同等です。

(lambda (x) (* x x)) 
(function (lambda (x) (* x x))) 
#'(lambda (x) (* x x))

20年前のEmacsバージョンをサポートしようとする以外に、ラムダを明確に引用する理由はありません。

そうしないでください。


補足として:

  • ラムダを(と一緒に')ハードクォートすることで違いが生じ、バイトのコンパイルが妨げられます。私はそれが有用なシナリオを考えることはできませんが、誰が知っています。

  • 何らかの理由でレキシカルバインディングを使用していない場合にのみ、バックティックはラムダで本当に役立つ唯一の引用です。


バイトコンパイルでの引用の効果を説明する例を含むマニュアルの匿名関数セクションへのリンクを追加することを検討してください。
コンスタンティン14年

@Constantine完了。私は電話をしているので、私は怠け者になりました、とにかくOPはすでにそれをリンクしました。
マラバルバ14年

字句バインディングとバックティックを使用しないことの意味を明確にできますか?ありがとう。
コアダンプ14年

@coredump動的バインディングでは、ラムダ内で外部変数にアクセスできるようにする唯一の方法は、ラムダを内部変数を持つリストとして手動で構築することです。Backticsはそのようなものに適しています。
マラバルバ14年

ところで、私は「昔々」が本当に当てはまるとは思いません。改訂履歴でこの主題を調べたとき、私はそれが行くために戻るためにlambda追加するマクロとして定義されていることがわかりましたfunction#'ある時点でIOW が必要になった場合、それは非常に初期の開発コードでした。確かに、Emacs-18ではすでに必要ではありませんでした。
ステファン

5

以来lambda、それが引用されていないときどんな意味がない、Emacs Lispに最近のバージョンは、引用符で囲まれていない解釈に(ANSI)のCommon Lispに従う(lambda...)よう#'(lambda...)。2つの表記はほぼ同じです(引用構造内を除く)。

好むか、(lambda...)それとも#'(lambda...)純粋にスタイルの問題です。一部の人々は、構文上のノイズを回避する裸の形式を好む一方、他の人(私を含む)は引用された形式を好む。


これは、elispマニュアルと矛盾しています:「Emacs Lispでは、そのようなリストは関数オブジェクトに評価される有効な式です。」
djechlin

8
「1990年以降にリリースされたバージョン」などの「最新バージョン」;
Stefan

0

# '(lambda ...)の歴史的遺産を見るために、少し歴史を追加しますか?

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=4290は以下を示唆しています:

Emacs 22以降、lambdaフォームが関数として使用される場合、その前にfunctionor が付いているかどうかに関係なく、バイトコンパイルされ#'ます。22より前のEmacsバージョンでは、明示的に使用する#'function、フォームをバイトコンパイルする必要があります。

バイトコンパイラについては知りませんが、少なくとも1993年までは、lambdaマクロ自体が(function (lambda ...))フォームを返していたことがわかります。

https://www.iro.umontreal.ca/~monnier/hopl-4-emacs-lisp.pdfは次のようにも述べています。

興味深いことに(MacLispとは異なり)、lambdaEmacs-19の開発初期にマクロとして追加された1991年頃まで、技術的にはElisp言語の一部ではありませんでした。Emacs-18では、匿名関数は次の形式の引用された値として記述されました。

'(lambda (..ARGS..) ..BODY..)

一方でlambda、マクロは今、ほぼ30年間、この引用が不要になりました、このような行為の多くのインスタンスはまだそれが身体のバイトコンパイルを防ぐことにもかかわらず、elispのコードで発生します。やや関連して、1993年にだけLucid Emacs 19.8 はMacLispから#'...読者の略記をインポートしました(function ...)。Emacsは翌年に続きました。


0

バックティックラムダ式を使用した実用的な例を挙げたいだけです。字句バインディング/変数シャドーイングについてです。バックティックラムダ式を使用し、コンマで変数を参照すると、グローバル値を取得できます。

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
             (let ((my-variable "Random"))
               (message ,my-variable)))))

M-x [RET] eval-buffer 「Random old」を出力します

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall (lambda()
             (let ((my-variable "Random"))
               (message my-variable)))))

M-x [RET] eval-buffer 「ランダム」を出力します

グローバル変数と変数のローカル変数を組み合わせた3番目の例

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
              (let ((my-variable "Random"))
                (message my-variable)
                (message ,my-variable)))))

M-x [RET] eval-buffer 「Random」「Random old」を出力します


私の例でのポイントではなかった@npostavsが、私は同様にその悪い習慣を避けるために、私の例を修正
cjohansson

良いのですが、これは内部バインディングに別の名前を選択するだけの改善であるとはまだ確信していません。
npostavs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.