";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))
Versi tanpa tanda kutip: Cobalah di codingground.
Versi kutipan : Cobalah di codingground.
Perhatikan bahwa outputnya terlihat seperti ini
> val it = "{some string}" : string
> val it = "{some string}" : string
{output to stdout}> val it = fn : string -> unit
karena kode deklarasi ditafsirkan oleh deklarasi (masing-masing ;
berakhir deklarasi) dan menunjukkan nilai dan jenis deklarasi masing-masing.
Latar Belakang
Di SML ada quine dari formulir <code>"<code in quotes>"
:
str(chr 34);(fn x=>print(x^it^x^it))"str(chr 34);(fn x=>print(x^it^x^it))"
dan satu dalam bentuk "<code in quotes>"<code>
:
";str(chr 34)^it;print(it^it)";str(chr 34)^it;print(it^it)
Keduanya mengandalkan fakta bahwa <code>
-part tidak mengandung tanda kutip dan dengan demikian dapat dikutip tanpa perlunya melarikan diri dari apa pun, yang "
dibutuhkan untuk menampilkan quine diberikan oleh str(chr 34)
.
Mereka juga sangat bergantung pada pengidentifikasi implisit it
yang digunakan ketika tidak ada pengidentifikasi eksplisit yang diberikan dalam deklarasi.
Di quine pertama str(chr 34);
mengikat it
string yang berisi "
, fn x=>
memulai fungsi anonim mengambil satu argumen x
, lalu menggabungkan x^it^x^it
dan mencetak string yang dihasilkan. Fungsi anonim ini langsung diterapkan ke string yang berisi kode program, sehingga rangkuman x^it^x^it
menghasilkan <code>"<code>"
.
Quine kedua dimulai dengan hanya kode program sebagai string ";str(chr 34)^it;print(it^it)";
yang terikat it
. Kemudian str(chr 34)^it;
merangkai kutipan ke awal string dan sekali lagi tidak ada pengidentifikasi eksplisit yang diberikan, string yang dihasilkan "<code>
terikat it
. Akhirnya print(it^it)
menyatukan string dengan menghasilkan sendiri "<code>"<code>
yang kemudian dicetak.
Penjelasan
Sunting: Tidak lagi up to date dengan versi 108-byte, namun orang mungkin memahaminya juga setelah membaca penjelasan ini.
Quine kutipan-aman menggabungkan kedua pendekatan di atas dan itu sendiri dari bentuk "<code>"<code>
. Menempatkan ini lagi dalam hasil ""<code>"<code>"
kuotasi, jadi kami mendapatkan string kosong dan kemudian quine dari bentuk lainnya.
Itu berarti program diberikan sumbernya sendiri dalam bentuk "<code>
oleh pengenal it
, atau it
adil "
dan kita diberi sumber kita sendiri <code>
sebagai argumen dan dengan demikian harus menjadi fungsi yang menangani argumen semacam itu.
(if size it>1then(print(it^it);fn _=>())else fn x=>print(it^it^x^it^x^it))
Untuk mengidentifikasi dalam kasus apa kita berada, kita memeriksa apakah ukurannya it
lebih besar dari 1. Jika tidak maka it
adalah "
dan kita berada dalam kasus kedua, sehingga else
-part mengembalikan fungsi anonim fn x=>print(it^it^x^it^x^it)
yang kemudian dipanggil karena diikuti oleh sumber sebagai string . Perhatikan kunci it^it^
yang diperlukan untuk string kosong di awal program.
Jika size it
lebih besar dari 1 kita berada di then
-part dan hanya perform print(it^it)
, kan? Tidak cukup, karena saya lalai memberi tahu Anda bahwa SML sangat diketik yang berarti bahwa conditional if <cond> then <exp_1> else <exp_2>
harus selalu memiliki tipe yang sama yang lagi berarti bahwa ekspresi <exp_1>
dan <exp_2>
perlu memiliki tipe yang sama. Kita sudah tahu tipe else
bagiannya: Fungsi anonim yang mengambil string dan kemudian panggilan print
memiliki tipestring -> <return type of print>
, dan print
memiliki tipe string -> unit
( unit
dalam beberapa hal mirip dengan void
dalam bahasa lain), jadi jenis yang dihasilkan adalah lagi string -> unit
.
Jadi jika then
bagian itu hanya print(it^it)
yang memiliki tipe unit
, kita akan mendapatkan kesalahan tipe ketidakcocokan. Jadi bagaimana fn _=>print(it^it)
? ( _
Adalah wildcard untuk argumen yang tidak digunakan) Fungsi anonim ini sendiri memiliki tipe di 'a -> unit
mana 'a
berdiri untuk tipe arbitrer, jadi dalam konteks kondisional kami yang memberlakukan string -> unit
tipe ini akan bekerja. (Variabel tipe 'a
akan dipakai dengan tipe string
.) Namun, dalam hal ini kami tidak akan mencetak apa-apa karena fungsi anonim tidak pernah dipanggil! Ingat, ketika kita masuk ke dalam then
-part kode keseluruhan "<code>"<code>
, jadi <code>
-part mengevaluasi ke suatu fungsi tetapi, karena tidak ada yang datang setelah itu, itu tidak dipanggil.
Sebaliknya, kita menggunakan sequentialisation yang memiliki bentuk (<exp_1>; ...; <exp_n>)
di mana <exp_1>
untuk <exp_n-1>
dapat memiliki jenis sewenang-wenang dan jenis dari <exp_n>
menyediakan jenis seluruh sequentialisation. Dari sudut pandang fungsional, nilai <exp_1>
to <exp_n-1>
hanya dibuang, namun SML juga mendukung konstruksi imperatif sehingga ekspresi mungkin memiliki efek samping. Singkatnya, kita ambil (print(it^it);print)
sebagai then
-bagian, dengan demikian mencetak terlebih dahulu dan kemudian mengembalikan fungsi print
yang memiliki tipe yang benar.