";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 ityang digunakan ketika tidak ada pengidentifikasi eksplisit yang diberikan dalam deklarasi.
Di quine pertama str(chr 34);mengikat itstring yang berisi ", fn x=>memulai fungsi anonim mengambil satu argumen x, lalu menggabungkan x^it^x^itdan mencetak string yang dihasilkan. Fungsi anonim ini langsung diterapkan ke string yang berisi kode program, sehingga rangkuman x^it^x^itmenghasilkan <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 itadil "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 itlebih besar dari 1. Jika tidak maka itadalah "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 itlebih 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 elsebagiannya: Fungsi anonim yang mengambil string dan kemudian panggilan printmemiliki tipestring -> <return type of print> , dan printmemiliki tipe string -> unit( unitdalam beberapa hal mirip dengan voiddalam bahasa lain), jadi jenis yang dihasilkan adalah lagi string -> unit.
Jadi jika thenbagian 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 -> unitmana 'aberdiri untuk tipe arbitrer, jadi dalam konteks kondisional kami yang memberlakukan string -> unittipe ini akan bekerja. (Variabel tipe 'aakan 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 printyang memiliki tipe yang benar.