Lisp で ' (または引用符) を使うのはいつですか? 質問する

Lisp で ' (または引用符) を使うのはいつですか? 質問する

入門的な Lisp の本の大部分を読み終えた後でも、特殊演算子(quote)(または同等の') 関数が何をするのかまだ理解できませんでしたが、これは私が見た Lisp コードのいたるところに見られました。

それは何をするためのものか?

ベストアンサー1

短い答えデフォルトの評価ルールをバイパスしてない式 (シンボルまたは s-exp) を評価し、入力されたとおりに関数に渡します。

長い答え: デフォルトの評価ルール

通常の関数 (これについては後で説明します) が呼び出されると、渡されたすべての引数が評価されます。つまり、次のように記述できます。

(* (+ a 2)
   3)

次に(+ a 2)、 と 2 を評価することによってを評価しますa。シンボルの値は、a現在の変数バインディング セットで検索され、置き換えられます。a現在、 は値 3 にバインドされています。

(let ((a 3))
  (* (+ a 2)
     3))

となり(+ 3 2)、+ は 3 と 2 で呼び出され、5 が生成されます。元の形式では(* 5 3)15 が生成されます。

もう説明してquoteよ!

わかりました。上記のように、関数のすべての引数は評価されるので、シンボル a値ではなく、シンボルとして扱われる場合は、評価する必要はありません。Lisp シンボルは、値としても、ハッシュ テーブルのキーなど、他の言語では文字列が使用されるマーカーとしても使用できます。

ここで、 のquote出番です。Python アプリケーションからのリソース割り当てをプロットしたいが、プロットは Lisp で行うとします。Python アプリケーションで次のようにします。

print("'(")
while allocating:
    if random.random() > 0.5:
        print(f"(allocate {random.randint(0, 20)})")
    else:
        print(f"(free {random.randint(0, 20)})")
    ...
print(")")

出力は次のようになります (少し見栄えを良くしています)。

'((allocate 3)
  (allocate 7)
  (free 14)
  (allocate 19)
  ...)

("tick")によってデフォルトのルールが適用されなくなると言ったことを覚えていますか? いいですね。そうしないと、とquoteの値が検索されてしまいますが、これは望ましくありません。Lisp では、次のようにします。allocatefree

(dolist (entry allocation-log)
  (case (first entry)
    (allocate (plot-allocation (second entry)))
    (free (plot-free (second entry)))))

上記のデータの場合、次の一連の関数呼び出しが行われます。

(plot-allocation 3)
(plot-allocation 7)
(plot-free 14)
(plot-allocation 19)

しかし、 についてはどうでしょうかlist?

まあ、時にはする引数を評価したい。数値と文字列を操作し、その結果のリストを返す気の利いた関数があるとします。まずは間違ったスタートを切ってみましょう。

(defun mess-with (number string)
  '(value-of-number (1+ number) something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))

おい!それは私たちが望んでいたことじゃない。選択的にいくつかの引数を評価し、その他はシンボルのままにします。#2 を試してください。

(defun mess-with (number string)
  (list 'value-of-number (1+ number) 'something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)

だけではなくquotebackquote

ずっと良くなりました! ちなみに、このパターンは (主に) マクロで非常に一般的なので、まさにそれを実行するための特別な構文があります。バッククォート:

(defun mess-with (number string)
  `(value-of-number ,(1+ number) something-with-string ,(length string)))

これは を使用するのと似ていますquoteが、引数の前にコンマを付けることで、一部の引数を明示的に評価するオプションがあります。結果は を使用するのと同等ですlistが、マクロからコードを生成する場合は、返されたコードの小さな部分のみを評価したい場合が多いので、バッククォートの方が適しています。リストが短い場合は、 の方listが読みやすくなります。

おい、 を忘れてたぞquote

では、これはどういった意味を持つのでしょうか?そうそう、はquote実際に何をするのでしょうか?単に引数を評価せずに返すだけです!最初に通常の関数について述べたことを覚えていますか?いくつかの演算子/関数はない引数を評価します。たとえば、IF の場合、else 分岐が採用されなかった場合は評価したくないですよね? いわゆる特殊演算子マクロと一緒に使用すると、そのように動作します。特殊演算子は言語の「公理」でもあり、最小限のルール セットです。これに基づいて、さまざまな方法で組み合わせることで、Lisp の残りの部分を実装できます。

quoteさて、に戻ります。

Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL

Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL

比較(Steel-Bank Common Lisp の場合):

Lisp> spiffy-symbol
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING   {A69F6A9}>:
  The variable SPIFFY-SYMBOL is unbound.

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-INT:SIMPLE-EVAL-IN-LEXENV SPIFFY-SYMBOL #<NULL-LEXENV>)
0] 

spiffy-symbol現在のスコープ内には存在しないからです。

まとめ

quotebackquote(カンマ付き)、およびは、listリストを作成するために使用するツールの一部です。リストは値のリストであるだけでなく、ご覧のとおり軽量の( を定義する必要がないstruct)データ構造としても使用できます。

もっと詳しく知りたい方はピーター・セイベルの本をお勧めします実用的な Common Lispすでにプログラミング全般に興味があるなら、Lispを学ぶための実践的なアプローチとして、Ron GarretのCommon Lisp パッケージの初心者向けガイドそれらについて良い説明をします。

楽しいハッキングを!

おすすめ記事