val()=hd[(fn s=>let val$ =s^"\""^String.toString s^"\"]"val(189,%)=(size$,$)in print%end)"val()=hd[(fn s=>let val$ =s^\"\\\"\"^String.toString s^\"\\\")\"val(189,%)=(size$,$)in print%end)"]
Cobalah online!
Untuk MLton, program SML lengkap adalah ekspresi dibatasi dan diakhiri oleh ;
(misalnya print"Hello";print"World";
) atau deklarasi dengan var
dan fun
kata kunci (misalnya var _=print"Hello"var _=print"World"
) di mana _
kartu liar yang juga dapat diganti dengan nama variabel apa pun.
Opsi pertama tidak berguna untuk pemrograman murni karena ;
dengan sendirinya adalah program yang valid (yang tidak melakukan apa-apa, tetapi tidak salah juga). Masalah dengan pendekatan kedua adalah bahwa deklarasi seperti var _=print"Hello"
dapat disingkat menjadi hanya var _="Hello"
(atau bahkan var _=print
) karena deklarasi denganvar
karya selama sisi kanan adalah ekspresi atau nilai SML yang valid (SML adalah bahasa fungsional, sehingga fungsi dapat digunakan sebagai nilai juga).
Pada titik ini, saya siap untuk menyatakan pemrograman asli di SML tidak mungkin, ketika kebetulan saya menemukan pencocokan pola di val
-deklarasi. Ternyata sintaks untuk deklarasi tidak val <variable_name> = <expression>
tetapi val <pattern> = <expression>
, di mana pola dapat terdiri dari nama variabel, konstanta dan konstruktor. Karena print
fungsi memiliki tipestring -> unit
, kita bisa menggunakan pola pertandingan di unit
-nilai ()
untuk menegakkan bahwa fungsi cetak benar-benar diterapkan ke string: val()=print"Hey"
. Dengan pendekatan ini, menghapus salah satu print
atau "Hey"
menghasilkan Pattern and expression disagree
-tindakan.
Dengan cara ini mencetak murni, langkah selanjutnya adalah menulis quine, sebelum akhirnya beberapa penjaga perlu ditambahkan. Saya sebelumnya menggunakan teknik quine SML yang mudah (lihat sejarah revisi ), tetapi Anders Kaseorg menunjukkan pendekatan yang berbeda yang dapat menghemat beberapa byte dalam kasusnya. Menggunakan built-inString.toString
fungsi bawaan untuk menangani pelolosan string dan merupakan bentuk umum <code>"<data>"
, di mana "<data>"
adalah string pelolosan dari code
sebelumnya:
val()=(fn s=>print(s^"\""^String.toString s^"\""))"val()=(fn s=>print(s^\"\\\"\"^String.toString s^\"\\\"\"))"
Ini adalah quine yang berfungsi tetapi belum asli. Pertama-tama Anders Kaseorg mengetahui bahwa MLton menerima satu kutipan"
sebagai kode tanpa menghasilkan kesalahan, yang berarti kita tidak dapat memiliki kode yang diakhiri dengan penawaran seperti di atas. Cara terpendek untuk mencegah hal ini adalah dengan membungkus semuanya setelah val()=
dalam tanda kurung, namun kemudian kode dapat dikurangi menjadi val()=()
. Cara terpendek kedua yang saya temukan adalah menggunakan val()=hd[ ... ]
, yaitu kita membungkus semuanya menjadi daftar dan mengembalikan elemen pertamanya untuk membuat pemeriksa tipe senang.
Untuk memastikan bahwa tidak ada bagian dari string data yang dapat dihapus tanpa diketahui, pencocokan pola di val
-deklarasikan berguna lagi: Panjang string terakhir yang akan dicetak (dan dengan demikian panjang program) harus sama dengan 195, jadi kita bisa menulis let val t=... val 195=size t in print t end
di badan fn
abstraksi bukan print(...)
. Menghapus bagian dari string menghasilkan panjang kurang dari 189, sehingga menyebabkan Bind
pengecualian dilemparkan.
Masih ada masalah yang tersisa: seluruh val 195=size t
pemeriksaan bisa dibatalkan. Kami dapat mencegah hal ini dengan memperluas cek agar sesuai dengan tuple:, val t=... val(216,u)=(n+size t,t)in print u end
sehingga menghapus hasil cek dalam variabel tidak terikat u
.
Secara keseluruhan, ini menghasilkan solusi 195 byte berikut:
val()=hd[(fn s=>let val t=s^"\""^String.toString s^"\")"val(195,u)=(size t,t)in print u end)"val()=hd[(fn s=>let val t=s^\"\\\"\"^String.toString s^\"\\\")\"val(195,u)=(size t,t)in print u end)"]
Menerapkan trik golf menggunakan nama variabel operator seperti !
, $
dan %
bukannya n
, t
danu
untuk menghemat ruang putih (lihat tip ini ) mengarah ke versi 182 byte terakhir.
Semua pemindahan substring lainnya yang tidak secara eksplisit dinyatakan dalam penjelasan harus menghasilkan sintaks atau tipe kesalahan.
Sunting 1: length(explode t)
adil size t
.
Sunting 2: Terima kasih kepada Anders Kaseorg untuk pendekatan quine yang berbeda dan menunjukkan "kerentanan".