不正行為¹ を除けば、コンパイルされた言語と解釈された言語の間に違いはありません。
クインへの一般的なアプローチは非常に簡単です。まず、プログラムがどのようなものであれ、ある時点で何かを出力する必要があります:
印刷 ...
しかし、何を印刷すればよいのでしょうか? 自体。したがって、「印刷」コマンドを印刷する必要があります。
印刷「印刷...」
次に何を印刷しますか?その間、プログラムは大きくなったため、"print" で始まる文字列も出力する必要があります。
print "print \"print ...\""
プログラムが再び大きくなったので、印刷するものがまた増えました。
print "print \"print \\\"...\\\"\""
等々。コードを追加するたびに、印刷するコードが増えます。このアプローチはうまくいきませんが、興味深いパターンが明らかになります: 文字列 "print \"" が何度も繰り返されます。繰り返し部分を変数に入れるとよいでしょう:
a = "印刷\""
印刷する
ただし、プログラムが変更されたばかりなので、以下を調整する必要があります。
a = "a = ...\n印刷 a"
印刷する
「...」を入力しようとすると、以前と同じ問題に遭遇します。最終的には、次のように書きたいと思います。
a = "a = " + (a の内容を引用) + "\nprint a"
印刷する
しかし、それは不可能です。なぜならquoted()
、引用のためのそのような関数があったとしても、それ自体に関して定義する問題がまだあるa
からです:
a = "a = " + quoted(a) + "\nprint a"
印刷する
したがって、私たちができる唯一のことは、プレースホルダーを に入れることですa
:
a = "a = @\nprint a"
印刷する
そして、それがすべてのトリックです!他のことはもう明らかです。プレースホルダーを次の引用された内容に置き換えるだけですa
。
a = "a = @\nprint a"
print a.replace("@", quoted(a))
コードを変更したため、文字列を調整する必要があります。
a = "a = @\nprint a.replace(\"@\", quoted(a))"
print a.replace("@", quoted(a))
以上です!すべての言語のすべてのクインはそのように機能します (不正行為を除く)。
そうですね、プレースホルダーの最初の出現のみを置き換えるようにする必要があります。また、2 番目のプレースホルダーを使用すると、文字列を引用する必要がなくなります。
しかし、これらは小さな問題であり、簡単に解決できます。quoted()
実際には、との実現はreplace()
、さまざまなクインが実際に異なる唯一の詳細です。
¹ プログラムにソース ファイルを読み込ませる