Catatan Lane: Bertemu hari ini di Twitter sangat lucu, sekilas, utas. Dan kemudian dia melihat lebih dekat dan menyadari bahwa dia tidak hanya lucu, tetapi juga menghibur. Dan karena kebetulan hari ini adalah hari Jumat, saya memutuskan bahwa ada baiknya berbagi temuan dengan teman-teman saya :)
Simpan program berikut di /tmp/quine.pl
Illegal division by zero at /tmp/quine.pl line 1.
Jalankan dengan perintah
perl /tmp/quine.pl
dan dia akan menampilkan kodenya sendiri.
"Trik-gempa" cukup sederhana untuk dikomposisikan dalam banyak bahasa pemrograman, di mana kesalahan sintaksis dalam sumber memprovokasi parser untuk menghasilkan kesalahan yang akan bertepatan dengan kode sumber program. Saya
memposting beberapa trik ini di Twitter , termasuk yang berikut:
File "quine.py", line 1 File "quine.py", line 1 ^ IndentationError: unexpected indent
Tapi jelai mutiara di awal artikel ini adalah trik yang sama sekali berbeda - program ini mengerti
dengan benar .
Dan itu tidak bekerja lama, sampai tersandung pada kesalahan pembagian dengan nol. Quine ini sangat sensitif terhadap penamaan file - misalnya, menjalankan ./quine.pl tidak akan berfungsi.
Jadi pesan kesalahan ini sebenarnya seluruh program ?!
Program ini menggunakan banyak bar mutiara do-what-I-mean-parser.
Simbol / sangat tergantung pada konteks aplikasi dan dapat dianggap sebagai simbol pembagian, atau sebagai awal ekspresi reguler. Dan bahkan perubahan kecil dalam kode program ini menyebabkan kesalahan dalam menguraikan keteraturan, dan bukan untuk mengeksekusi kode. Dalam hal ini, kedua / karakter muncul dalam konteks operator.
Bagian non-kamus lain dari program ini adalah
1.
, yang ditafsirkan hanya sebagai angka dan
.
yang merupakan operator gabungan.
Lalu apa arti kata-kata itu?
Kata-kata dalam Perl dapat berupa nama rutin, metode, paket, atau kelas. Atau (dalam mode malas) baris tanpa pemisah atau bahkan mungkin sesuatu yang saya lupa!
Perl juga menggunakan sintaks pemanggilan metode yang tidak biasa yang disebut "
sintaks objek tidak langsung ", yang terlihat seperti ini:
paling sering Anda bisa melihat caranya
print $filehandle "message"; my $instance = new Class(args);
meskipun untuk Perl, sintaks berikut lebih disukai:
$filehandle->print("message"); my $instance = Class->new(args);
Dokumentasi
perlobj mengatakan:
Perl menggunakan heuristik untuk mem-parsing kode ini, berdasarkan pada nama paket apa yang diketahuinya, subrutin apa yang ada dalam paket saat ini, kata-kata apa yang telah ditemui sebelumnya dan menganalisis data input lainnya. Tidak perlu dikatakan, heuristik dapat menghasilkan hasil yang sangat tak terduga!
Bagaimana dia menguraikan kode ini?
Mulai dari sisi kanan
pl line 1.
diuraikan sebagai pemanggilan metode
line->pl(1.)
di mana baris adalah nama paket (kelas), dan pl adalah metodenya.
Di tengah, "at", "tmp" dan "quine" diurai sebagai kata-kata sederhana, mis. string. Ekspresi diuraikan sebagai berikut:
(("at" / "tmp") / "quine") . line->pl(1.)
Di sebelah kiri adalah dua panggilan metode tidak langsung dilipat,
division->Illegal(zero->by( ... ))
Ekspresi internal yang dieksekusi pertama adalah:
"at" / "tmp"
Dan ini secara instan menyebabkan pembagian dengan pengecualian nol.