Dalam pengembaraan siri blog Quine sebelum ini, kami meneroka cara menulis Quines dan Intron kami sendiri. Hari ini kita akan melihat apakah itu QuineRelays dan cara anda boleh memanfaatkan Intron untuk menciptanya.
Bayangkan bulatan program, setiap satu ditulis dalam bahasa yang berbeza. Setiap program dalam bulatan ini mempunyai satu tujuan: untuk mencetak kod sumber program seterusnya dalam urutan. Program terakhir kemudian menutup gelung dengan mencetak kod sumber program pertama.
Pada asasnya, QuineRelays ialah satu set n program, dalam n bahasa yang berbeza seperti:
Mari lihat beberapa contoh untuk memahami konsep dengan lebih baik.
QuineRelay pesanan ke-2 ini menampilkan program JavaScript yang mencetak program Python, yang kemudiannya mencetak semula program JavaScript asal. Ia merupakan duo dinamik replikasi diri.
JavaScript → Python ⥀
JavaScript: Cuba dalam talian!
console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q+[]})())`)})`)())
Python: Cuba dalam talian!
print("console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q+[]})())`)})`)())")
Perkara menjadi lebih menarik dengan QuineRelay pesanan ke-3. Yang ini bermula dengan atur cara Haskell, yang mengeluarkan atur cara Python, yang mengeluarkan atur cara Ruby, dan akhirnya, atur cara Ruby kembali kepada atur cara Haskell yang asal.
Haskell → Python2 → Ruby ⥀
Haskell: Cuba dalam talian!
q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')'] main=q "q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']" "def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'" "def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end"
Python2: Cuba dalam talian!
def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')' q("def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'","def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end","q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']")
Ruby: Cuba dalam talian!
def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end q("def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end","q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']","def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'")
Berikut ialah QuineRelay pesanan ke-4: Ruby → Java → C# → Python ⥀
GitHub
Merentas budaya, terdapat beberapa simbolisme yang dikongsi bersama. Salah satunya ialah Ouroboros, yang mempunyai rujukan dalam mitologi Mesir, Yunani, Rom, Hindu, Siberia, Norse, Afrika, dan Amerika Selatan. Ouroboros ialah simbol purba yang menggambarkan seekor ular atau naga memakan ekornya sendiri, mewakili kitaran kekal penciptaan dan kemusnahan.
Dalam mitologi Norse, Jörmungandr ialah seekor ular besar, anak tengah Loki dan gergasi Angrboða. Odin melemparkan Jörmungandr ke dalam lautan mengelilingi Midgard (alam manusia), di mana ular itu menjadi sangat besar sehingga ia mengelilingi dunia dan menggenggam ekornya sendiri. Akibatnya mengelilingi Midgard (Bumi) ia dirujuk sebagai Ular Dunia - Ouroboros. Jörmungandr melepaskan ekornya adalah salah satu tanda permulaan Ragnarök (pertempuran terakhir dunia).
Relay kui menjelmakan simbolisme ini dengan agak kemas, kerana setiap program dalam kitaran menghasilkan yang seterusnya, hanya untuk dilahirkan semula pada akhirnya, dan oleh itu digelar program Ouroboros.
Pegang pada tempat duduk anda. Berikut ialah Ouroboros QuineRelay pesanan ke-128. Ya, anda membacanya dengan betul. 128 !!!
Ruby → Rust → Scala → ... (120 yang lain) ... → Python → R → Ratfor → rc → REXX ⥀
GitHub
Seolah-olah ini tidak cukup menarik, ia termasuk telur easter. Kod Ruby asal apabila dizum keluar mengandungi naga Ouroboros!
Mari mulakan intron Python yang kami tulis sebelum ini dan cuba tukarkannya menjadi QuineRelay tertib ke-2.
Python Intron: Cuba dalam talian!
intron = 'wubbalubbadubdub' data = "print('intron =', repr(intron)); print('data =', repr(data)); print(data)" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
Menggunakan keajaiban intron, kini kita boleh dengan mudah meletakkan kod bahagian adik beradik Quine dalam bahasa berbeza ke dalam intron. Menghasilkan atur cara dalam bentuk:
Python:
intron = "code part of sibling" data = "code part of self" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
Memandangkan, setiap pembolehubah adalah adil, bertindak sebagai data Quine yang berbeza. Mari kita tukar nama data dan intron, masing-masing menjadi d1 dan d2.
Python:
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d1)
Kini, d2 bertindak sebagai intron, tetapi program di atas masih cuba mencetak sebahagian kod diri. Untuk mendapatkannya mencetak sumber seterusnya, mari cetak(d2) dan bukannya cetak(d1) pada penghujungnya.
Python:
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
Kita sedia maklum bahawa kandungan d1 hanyalah salinan baris 3. Tetapi kita belum mempunyai kandungan d2.
Katakanlah, kami mahu mencipta QuineRelay dengan JavaScript. Mari tulis intron yang serupa dalam JS.
JavaScript:
d1 = "code part of sibling" d2 = "code part of self" console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1);
Sekarang, baris 3 intron JS di atas, ialah kod program adik-beradik yang kami mahu!
Tampalkan kod satu sama lain sebagai intron pada yang lain.
Nota. Kita perlu menambah d1 + '' dalam js untuk mengelakkan beberapa ketidakpadanan petikan
Python: Try it online!
d1 = "print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)" d2 = "console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 + '');" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
JavaScript: Try it online!
d1 = "print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)" d2 = "console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 + '');" console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 + '');
There you go. It's a proper 2nd order QuineRelay! A Python program, that prints a JavaScript program, that prints the original Python program back in a cycle.
Creating a QuineRelay is an exercise in creative coding and understanding how different languages represent and manipulate strings. It involves weaving together introns from various programs, each containing the code to replicate its next neighbour.
At its core, an nth-order relay is a game of n clever ways to escape quotes across n programming languages.
Stay tuned for the next post on MultiQuine!
Sources and references:
Atas ialah kandungan terperinci QuineRelay: Kelahiran ular Quine. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!