シャープな引用はいつ使用すべきですか?


9

私は他の人のeLispコードで使用されている鋭い引用を見て、私はそれらを自分で使用しますが、それらが適切である場合とそうでない場合は完全には明確ではありません。

シャープ引用符を使用するのが適切な場合と、通常の単一引用符を代わりに使用する必要がある場合を正確に説明できますか?


3
nbここまたはSOでこの質問には多くの重複があります
phils


1
私はそれが重複しているとは思いません:emacs.stackexchange.com/questions/3595#'ラムダでの使用に関するものです(答えは基本的に「まったくない」)#'
ステファン

回答:


11

#'の省略形であるのとfunction同様に、'はの省略形ですquote

バイトコンパイラ、インタープリタ、または人間の読者に、引数が関数であることが期待される(として扱われる)ことを示す場所であればどこでも使用できます。

多くのコンテキストでは、たとえば、(または)を使用するのではなく、単にそれを引用符で囲む(quoteまたはまたは')場合、コンテキストは引数の処理方法を決定します。たとえば、シンボルがそのプロパティにのみ使用されている、つまり関数として使用されているコンテキストでは、単にシンボルを渡すことができます(たとえば、引用するか、値がシンボルである変数を渡すことにより)。#'functionsymbol-function

ただし#'、このようなコンテキストで使用すると、コードがより明確になる場合があります。Emacs-Lisp自体が、そのようなコンテキストでシンボルが関数として使用されていることを理解している場合でも、人間がコードを読む人にこれを強調するのに役立つ場合があります。

いくつかの他のLispでは、単純に(で引用されたラムダ形態の治療'使用引用場合)または引用符で囲まれていないされているが、機能位置での使用とは異なることができますfunction#')。しかし、Emacs Lispではありません。Emacs Lispでは、('または#'単にリストとしてではなく)関数として扱いたいラムダフォームを(またはを使用して)引用する必要はありません。自動車lambdaなどのリストだけで処理したい場合は、引用符で(')で囲んでください。以下の例でこれを示しています。

(elisp)匿名関数から

-特別なフォーム: function function-object

この特別なフォームはFUNCTION-OBJECT、評価せずに戻ります。

この点では、quote(* note Quoting::)に似ています。ただし、とは異なり quoteFUNCTION-OBJECT関数として使用することを目的としたEmacsエバリュエーターおよびバイトコンパイラへのメモとしても機能します。FUNCTION-OBJECT有効なラムダ式であるとすると、これには2つの効果があります。

•コードがバイトFUNCTION-OBJECTコンパイルされると、バイトコード関数オブジェクトにコンパイルされます(*注:Byte Compilation::)。

•字句バインドが有効な場合FUNCTION-OBJECT、クロージャに変換されます。*メモの閉鎖::。

読み取り構文#'は、を使用するための省略形functionです。次の形式はすべて同等です。

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

次の例ではchange-property、3番目の引数として関数を使用する関数を定義し、その後に無名関数を渡すことでdouble-property 使用する関数を定義しchange-propertyます。

(defun change-property (symbol prop function)
   (let ((value (get symbol prop)))
     (put symbol prop (funcall function value))))

(defun double-property (symbol prop)
   (change-property symbol prop (lambda (x) (* 2 x))))

lambdaフォームを引用しないことに注意してください。

上記のコードをコンパイルすると、無名関数もコンパイルされます。たとえば、リストとして引用して匿名関数を作成した場合、これは起こりません。

(defun double-property (symbol prop)
   (change-property symbol prop '(lambda (x) (* 2 x))))

その場合、無名関数は、コンパイルされたコードでラムダ式として保持されます。は関数のようchange-propertyに使用するつもりではないので、バイトコンパイラは、このリストが関数のように見えても、関数であると想定することはできません 。


9

#'(別名function)を前に使用でき(lambda ...)ますが、これは冗長なので、本当に意味があるのは、のようにシンボルの前だけ#'carです。ELispでは#'car'carほぼ完全に同等なので、主な目的の1つは、単に意図を文書化することです(つまり、この記号を関数として使用するつもりであることをこのコードを読む人に示すことです)。しかし、違いがより重要な状況がいくつかあります。

  • バイトコンパイラーは、この文書化された意図を利用しており、作成すると、関数として存在#'carするかどうかを確認carし、存在しない場合は、その関数を呼び出した場合と同様に警告を発します。
  • cl-fletおよび内でcl-labels#'f、ローカルシンボルのみを参照できますf。これ'fは、引き続きグローバルシンボルf(およびそのsymbol-functionスロットに格納されている可能性のある関数)を参照するためです。例えば

    (cl-flet ((car (x y) (+ x y)))
      (list #'car 'car))
    =>
    ((closure nil (x y) (+ x y)) car)
    
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.