Program qu ine lub quine to program, który po wykonaniu drukuje swój własny kod źródłowy. Quine nie może "wychodzić poza siebie", na przykład poprzez drukowanie zawartości pliku, w którym jest zawarty lub używanie zdolności introspekcyjnych do drukowania własnej reprezentacji. Zamiast tego musi obliczyć swój własny kod źródłowy.
Klasyczny sposób tworzenia takiego programu składa się z dwóch kroków:
- Inicjuje zmienną łańcuchową z symbolem zastępczym dla interpolacji.
- Wypisuje ciąg znaków i interpoluje go do siebie.
Sztuczka polega na tym, aby ciąg znaków był poprawny. Sposób, w jaki to zrobisz, różni się w zależności od języka i zależy od deklaracji zmiennych, potrzeby stosowania średników i podziałów wierszy, wymaganych cudzysłowów itp.
Bash
Podobnie jak większość rzeczy w Bashu, ten program wykorzystuje interesujące dziwactwo. Chociaż pojedyncze cudzysłowy są silnymi cudzysłowami i niczego nie rozszerzają, to printf
ósemkowe znaki specjalne jako znaki z określonym punktem kodowym:
s='s=%s;printf "$s" "$s"';printf "$s" "$s"
Python
W języku Python identyfikator formatu %r
Najprostszym sposobem na to jest zakończenie kodu znakiem nowej linii:
s='s=%r;print(s%%s)';print(s%s)
Jeśli chcesz, aby kod nie zawierał podziału wiersza, musisz napisać następujące polecenie:
s='s=%r;print(s%%s,sep="")';print(s%s,sep="")
JavaScript
Poniższe zapytania JavaScript działają pod node.js. Używają one console.log
, która zawsze dodaje nową linię, więc nowa linia jest wymagana na końcu każdego skryptu:
s="s=%j;console.log(s,s)";console.log(s,s)
Poniższy program jest również interesujący: nie drukuje całej swojej reprezentacji, ale opiera się na fakcie, że funkcje mają określoną reprezentację:
(function a(){console.log('('+a+')()')})()
Następny przykład jest bliski oszustwa, ponieważ eval
używany:
code='var q=unescape("%27");console.log("code="+q+code+q+";eval(code)")';eval(code)
Rdza
Rust zapewnia sposób cytowania argumentu w sformatowanym makrze drukowania, ale to makro wymaga, aby pierwszy argument makra drukowania był literałem łańcuchowym! Dlatego najlepiej jest użyć pozycyjnego identyfikatora argumentu:
fn main(){print!("fn main(){{print!({0:?},{0:?})}}","fn main(){{print!({0:?},{0:?})}}")}
PHP
Ten program PHP działa poprzez zapisanie kodu źródłowego w łańcuchu znaków, a następnie użycie funkcji printf
The 39
oznacza znak ASCII '
, aby poprawnie obsługiwać cudzysłowy w ciągu znaków:
<?php
$code = '<?php
$code = %c%s%c;
printf($code, 39, $code, 39);
';
printf($code, 39, $code, 39);
HQ9+
Ostatnim, ale nie mniej ważnym produktem jest HQ9+, który został opracowany przez Cliffa Biffle'a:
Q