Algol 60
Berikut adalah boolean procedure
yang melakukan apa yang ditanyakan oleh pertanyaan (catatan: Algol 60 didefinisikan dalam hal daftar token tanpa memperbaiki sintaks untuk mereka, di bawah ini menggunakan sintaks Marst untuk mewakili token individu yang membentuk program):
boolean procedure recursion detector(n);
boolean n;
begin
own boolean nested, seen nested;
boolean was nested, retval;
was nested := nested;
begin if nested then seen nested := true end;
nested := true;
retval := n; comment "for the side effects, we ignore the result";
nested := was nested;
retval := seen nested;
begin if ! nested then seen nested := false end;
recursion detector := retval
end;
Verifikasi
Berikut kode tes yang saya gunakan:
procedure outboolean(c, b);
integer c;
boolean b;
begin
if b then outstring(c, "true\n") else outstring(c, "false\n")
end;
begin
outboolean(1, recursion detector(false));
outboolean(1, recursion detector(true));
outboolean(1, recursion detector(recursion detector(false)));
outboolean(1, recursion detector(false | recursion detector(true)));
outboolean(1, recursion detector(false & recursion detector(true)));
outboolean(1, recursion detector(recursion detector(recursion detector(false))))
end
Seperti yang diharapkan, outputnya adalah:
false
false
true
true
true comment "because & does not short-circuit in Algol 60";
true
Penjelasan
Algol 60 memiliki urutan evaluasi yang berbeda dari kebanyakan bahasa, yang memiliki logika sendiri, dan sebenarnya jauh lebih kuat dan umum daripada urutan evaluasi yang khas, tetapi cukup sulit bagi manusia untuk mendapatkan kepala mereka sekitar (dan juga cukup sulit untuk komputer untuk diimplementasikan secara efisien, itulah sebabnya ia diubah untuk Algol 68). Ini memungkinkan untuk solusi tanpa kecurangan (program tidak perlu melihat pohon parse atau semacamnya, dan tidak seperti hampir semua solusi lain di sini, ini akan bekerja dengan baik jika panggilan bersarang dilakukan melalui FFI).
Saya juga memutuskan untuk memamerkan beberapa kebiasaan bahasa lainnya. (Khususnya, nama variabel dapat berisi spasi putih; ini cukup berguna untuk dibaca, karena mereka tidak dapat berisi garis bawah. Saya juga menyukai kenyataan bahwa indikator komentar adalah kata literal comment
dalam sebagian besar penyandian sintaksis. Algol 68 menemukan ini cukup canggung untuk pendeknya komentar, dan diperkenalkan ¢
sebagai alternatif. Kutipan di sekitar badan komentar biasanya tidak diperlukan, saya hanya menambahkannya untuk kejelasan dan untuk mencegah komentar secara tidak sengaja berakhir ketika saya mengetikkan titik koma.) Saya sebenarnya sangat menyukai konsep luas bahasa (jika bukan detailnya), tetapi sangat verbose sehingga saya jarang menggunakannya di PPCG.
Cara utama di mana Algol 60 berbeda dari bahasa yang diilhami (seperti Algol 68, dan secara tidak langsung C, Java, dll; orang yang tahu K&R C mungkin akan mengenali sintaks ini untuk fungsi) adalah bahwa argumen fungsi diperlakukan agak seperti lambda kecil sendiri; misalnya, jika Anda memberikan argumen 5
ke fungsi yang hanya angka 5, tetapi jika Anda memberikan argumen x+1
Anda mendapatkan apa yang Anda tentukan, konsep " x
plus 1", bukan hasil dari x
plus 1. Perbedaannya di sini adalah bahwa jika x
perubahan, kemudian mencoba untuk mengevaluasi argumen fungsi yang bersangkutan akan melihat baru nilaix
. Jika argumen fungsi tidak dievaluasi di dalam fungsi, itu tidak akan dievaluasi di luar fungsi juga; juga, jika dievaluasi beberapa kali di dalam fungsi, itu akan dievaluasi secara terpisah setiap kali (dengan asumsi bahwa ini tidak dapat dioptimalkan). Ini berarti bahwa dimungkinkan untuk melakukan hal-hal seperti menangkap fungsi, katakanlah, if
atau while
dalam suatu fungsi.
Dalam program ini, kami mengeksploitasi fakta bahwa jika panggilan ke suatu fungsi muncul dalam argumen ke fungsi itu, itu berarti bahwa fungsi tersebut akan berjalan secara rekursif (karena argumen tersebut dievaluasi tepat pada titik atau titik yang dievaluasi oleh fungsi fungsi itu. , tidak lebih awal atau lebih lambat, dan ini harus berada di dalam fungsi body). Ini mengurangi masalah untuk mendeteksi jika fungsi berjalan secara rekursif, yang jauh lebih mudah; yang Anda butuhkan adalah variabel thread-lokal yang merasakan jika ada panggilan rekursif (ditambah, dalam hal ini, yang lain untuk mengkomunikasikan informasi kembali dengan cara lain). Kita dapat menggunakan variabel statis (misown
) untuk tujuan tersebut, karena Algol 60 adalah single-threaded. Yang harus kita lakukan setelah itu adalah mengembalikan semuanya seperti semula, sehingga fungsinya akan berfungsi dengan benar jika dipanggil beberapa kali (seperti yang disyaratkan oleh aturan PPCG).
Fungsi tidak mengembalikan nilai yang diinginkan dari panggilan dalam saat ini (setidaknya jika Anda menganggap mereka harus mencari panggilan sendiri hanya dalam argumen mereka , daripada menghitung sendiri); membuat pekerjaan itu cukup mudah menggunakan prinsip-prinsip umum yang sama, tetapi lebih kompleks dan akan mengaburkan cara kerja fungsi. Jika itu dianggap perlu untuk mematuhi pertanyaan, itu seharusnya tidak terlalu sulit untuk diubah.
print(func(), func(func()))
, atau apakah hanya akan ada panggilan tingkat atas ke fungsi segera setelah ditetapkan?