入門的な 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 では、次のようにします。allocate
free
(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)
だけではなくquote
、backquote
ずっと良くなりました! ちなみに、このパターンは (主に) マクロで非常に一般的なので、まさにそれを実行するための特別な構文があります。バッククォート:
(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
現在のスコープ内には存在しないからです。
まとめ
quote
、backquote
(カンマ付き)、およびは、list
リストを作成するために使用するツールの一部です。リストは値のリストであるだけでなく、ご覧のとおり軽量の( を定義する必要がないstruct
)データ構造としても使用できます。
もっと詳しく知りたい方はピーター・セイベルの本をお勧めします実用的な Common Lispすでにプログラミング全般に興味があるなら、Lispを学ぶための実践的なアプローチとして、Ron GarretのCommon Lisp パッケージの初心者向けガイドそれらについて良い説明をします。
楽しいハッキングを!