(~!)(!)((~)~*):((!)~^)*(:^)(~(!)~^(~)~*)(()~(~)~^~*)
Cobalah online! (termasuk bagian testuite dan teks yang mengidentifikasi program)
Skor ini mengejutkan baik untuk esolang tingkat sangat rendah. (Angka Gereja, boolean Gereja, dll. Sangat umum digunakan di Underload karena alasan ini; bahasa tidak memiliki angka dan boolean yang tertanam di dalamnya, dan ini adalah salah satu cara yang lebih mudah untuk mensimulasikannya. Karena itu, juga umum untuk menyandikan booleans sebagai angka Gereja 0 dan 1.)
Bagi siapa pun yang bingung: Underload memungkinkan Anda mendefinisikan fungsi yang dapat digunakan kembali, tetapi tidak membiarkan Anda memberi nama dengan cara biasa, Underload hanya mengitari tumpukan argumen (jadi jika Anda mendefinisikan lima fungsi dan ingin memanggil yang pertama Anda mendefinisikan, Anda perlu menulis fungsi baru yang membutuhkan lima argumen dan memanggil kelima argumen tersebut, lalu menyebutnya dengan cukup banyak argumen sehingga mencari argumen cadangan yang akan digunakan). Memanggil mereka menghancurkannya secara default tetapi Anda dapat memodifikasi panggilan untuk membuatnya tidak merusak (dalam kasus sederhana, Anda hanya perlu menambahkan tanda titik dua pada panggilan tersebut, meskipun kasing kompleks lebih umum karena Anda perlu memastikan bahwa salinannya di stack tidak menghalangi jalan Anda), jadi dukungan fungsi Underload memiliki semua persyaratan yang kita perlukan dari pertanyaan.
Penjelasan
benar
(~!)
( ) Define function:
~ Swap arguments
! Delete new first argument (original second argument)
Yang ini cukup mudah; kita menyingkirkan argumen yang tidak kita inginkan dan argumen yang kita inginkan hanya tinggal di sana, berfungsi sebagai nilai balik.
Salah
(!)
( ) Define function:
! Delete first argument
Yang ini bahkan lebih mudah.
tidak
((~)~*)
( ) Define function:
~* Modify first argument by pre-composing it with:
(~) Swap arguments
Ini menyenangkan: not
tidak menyebut argumen sama sekali, itu hanya menggunakan komposisi fungsi. Ini adalah trik umum di Underload, di mana Anda sama sekali tidak memeriksa data Anda, Anda hanya mengubah cara kerjanya dengan melakukan pra dan pasca membuat sesuatu dengan itu. Dalam hal ini, kami memodifikasi fungsi untuk menukar argumennya sebelum menjalankan, yang jelas meniadakan angka Gereja.
dan
:((!)~^)*
( ) Define function:
~^ Execute its first argument with:
(!) false
{and implicitly, our second argument}
* Edit the newly defined function by pre-composing it with:
: {the most recently defined function}, without destroying it
Pertanyaannya memungkinkan mendefinisikan fungsi dalam hal fungsi lain. Kami mendefinisikan "dan" selanjutnya karena semakin baru "tidak" telah ditentukan, semakin mudah untuk menggunakannya. (Ini tidak mengurangi skor kami, karena kami tidak menyebutkan "tidak" sama sekali, tetapi menghemat byte dari penulisan definisi lagi. Ini adalah satu-satunya waktu dimana satu fungsi merujuk ke yang lain, karena merujuk ke fungsi apa pun tetapi yang paling baru didefinisikan akan menelan biaya terlalu banyak byte.)
Definisi di sini adalah and x y = (not x) false y
. Dengan kata lain, jika not x
, maka kita kembali false
; jika tidak, kami kembali y
.
atau
(:^)
( ) Define function:
: Copy the first argument
^ Execute the copy, with arguments
{implicitly, the original first argument}
{and implicitly, our second argument}
@Nitrodon menunjukkan dalam komentar yang or x y = x x y
biasanya lebih pendek dari or x y = x true y
, dan itu ternyata benar di Underload juga. Implementasi yang naif akan menjadi (:~^)
, tetapi kita bisa bermain golf byte tambahan dengan mencatat bahwa tidak masalah apakah kita menjalankan argumen pertama asli atau salinannya, hasilnya sama saja.
Underload sebenarnya tidak mendukung currying dalam arti yang biasa, tetapi definisi seperti ini membuatnya terlihat seperti itu! (Kuncinya adalah bahwa argumen yang tidak dikonsumsi hanya bertahan, sehingga fungsi yang Anda panggil akan menafsirkannya sebagai argumen sendiri.)
tersirat
(~(!)~^(~)~*)
( ) Define function:
~ Swap arguments
~^ Execute the new first (original second) argument, with argument:
(!) false
{and implicitly, our second argument}
(~)~* Run "not" on the result
Definisi yang digunakan di sini adalah implies x y = not (y false x)
. Jika y benar, ini disederhanakan menjadi not false
, yaitu true
. Jika y salah, ini disederhanakan not x
, sehingga memberi kita tabel kebenaran yang kita inginkan.
Dalam hal ini, kami menggunakan not
lagi, kali ini dengan menulis ulang kodenya daripada merujuknya. Itu hanya ditulis secara langsung karena (~)~*
tanpa tanda kurung di sekitarnya, sehingga dipanggil daripada didefinisikan.
xor
(()~(~)~^~*)
( ) Define function:
~ ~^ Execute the first argument, with arguments:
(~) "swap arguments"
() identity function
~* Precompose the second argument with {the result}
Kali ini, kami hanya mengevaluasi satu dari dua argumen kami, dan menggunakannya untuk menentukan apa yang akan dikomposisikan ke argumen kedua. Underload memungkinkan Anda bermain dengan cepat dan longgar dengan arity, jadi kami menggunakan argumen pertama untuk memilih antara dua fungsi dua-argumen dua-kembali; argumen swap yang mengembalikan keduanya tetapi dalam urutan yang berlawanan, dan fungsi identitas yang mengembalikan keduanya dalam urutan yang sama.
Ketika argumen pertama benar, oleh karena itu kami menghasilkan versi yang diedit dari argumen kedua yang bertukar argumen sebelum berjalan, yaitu precompose dengan "swap argumen", yaitu not
. Jadi argumen pertama yang benar berarti kita mengembalikan not
argumen kedua. Di sisi lain, argumen pertama palsu berarti kita menulis dengan fungsi identitas, yaitu tidak melakukan apa pun. Hasilnya adalah implementasi dari xor
.