Квайны
Определение: |
Квайном (англ. quine)[1] называется программа, которая выводит свой исходный код. При этом, программа не должна использовать внешние данные (например, читать файл со своим исходным кодом). |
Стоит отметить, что программы, использующие для чтения своего кода файловую систему, квайнами не считаются. Например, программа на BASIC вида
10 LIST
выводит на экран свой исходный код, поскольку команда
просит среду исполнения вывести в консоль текущую программу (эта функция была необходима для программистов, так как код программы зачастую не мог поместиться на консоль 80x25 символов).Квайн состоит из двух сегментов: кода и данных. Данные представляют собой текстовую версию кода, и, как правило, получаются из кода простым добавлением обрамляющих кавычек. Код, в свою очередь, сначала использует данные, чтобы вывести код, содержащийся в них, а затем просто выводит данные.
Формально общий принцип написания квайнов содержится в доказательстве теоремы о рекурсии. Далее будет рассмотрено понятие мультиквайна.
Мультиквайны
Связанные определения
Определение: |
Интроном (англ. intron)[2] называется часть сегмента данных, которая не используется для вывода кода, но сохраняется в процессе саморепликации квайна. |
Определение: |
Биквайном (англ. biquine) называется программа, которая делает одно из двух:
|
Определение: |
-квайном (англ. -quine) называется программа, способная вывести исходный код программ на других языках программирования в зависимости от переданного ей аргумента, а также свой исходный код при вызове без аргументов. |
Заметим, что требование, чтобы программы были на разных языках программирования, важно, иначе все программы смогут иметь один и тот же код.
Теорема (о существовании мультиквайнов): |
На любом языке программирования можно написать мультиквайн. |
Доказательство: |
Докажем утверждение для биквайна, для большего количества языков доказательство будет выглядеть аналогично. Рассмотрим программу с двумя параметрами на языке , которая выводит первый параметр при обычном запуске и второй — при запуске со спец. аргументом. По теореме о рекурсии мы можем зафиксировать первый параметр и сказать, что он будет равен исходному коду нашей программы. Таким образом, мы получим программу с одним параметром, которая выводит свой код при запуске без аргументов и выводит параметр при запуске со спец. аргументом. Проделаем то же самое для программы на языке . И, наконец, зафиксируем как параметр первой программы исходный код второй и наоборот. |
Принцип написания
Будем следовать доказательству и напишем мультиквайн для двух языков. Далее покажем, как добавить новый язык.
- напишем для каждого языка "полуквайн":
:
if (arg == "print second!")
print(p)
else
print(getSrc())
|
:
if (arg == "print first!")
print(p)
else
print(getSrc())
|
- подставим код второй программы в первую:
: if (arg == "print second!") print( (p, arg).getSrc()) else print(getSrc())
- применим теорему о рекурсии и заменим параметр на исходный код программы:
: if (arg == "print second!") print( (getSrc(), arg).getSrc()) else print(getSrc())
Вторая программа может быть получена запуском первой с нужным аргументом.
Теперь добавим третий язык:
- напишем для него "полуквайн", но уже с двумя параметрами и тремя возможными выводами:
:
if (arg == "print first!")
print(p1)
elseif (arg == "print second!")
print(p2)
else
print(getSrc())
- добавим параметр в два уже существующих квайна:
: if (arg == "print second!") print( (p, getSrc(), arg).getSrc()) elseif (arg == "print third!") print(p) else print(getSrc()) |
: if (arg == "print first!") print( (p, getSrc(), arg).getSrc()) elseif (arg == "print third!") print(p) else print(getSrc()) |
- подставим код первых двух в третью:
: if (arg == "print first!") print( (p1, arg).getSrc()) elseif (arg == "print second!") print( (p2, arg).getSrc()) else print(getSrc())
- применим теорему о рекурсии и заменим оба параметра на исходный код программы:
: if (arg == "print first!") print( (getSrc(), arg).getSrc()) elseif (arg == "print second!") print( (getSrc(), arg).getSrc()) else print(getSrc())
Две оставшиеся программы будут выглядеть аналогично и смогут быть получены путём запуска третьей с каждым из возможных аргументов.
Примечания
- ↑ Название "квайн" было предложено Дугласом Хофштадтером, в его известной книге "Гёдель, Эшер, Бах: Эта бесконечная гирлянда" в честь американского логика и философа Уилларда Ван Ормана Квайна, который углублённо изучал явление косвенного самоупоминания.
- ↑ Название пришло из биологии, где интронами называются части ДНК, не участвующие в синтезе протеинов.