7 Evaluasi Ekspresi dan Persamaan
8.3 Type Penyebutan satu per satu (Enumeration Types)
Type seperti type Built-In Bool, yang hanya terdiri dari simbol const nullary, disebut juga type penyebutan satu per satu (enumeration types). Kamu dapat dengan mudah menggambarkan type seperti itu sendiri, e.g.:
type Day = const sun, mon, tue, wed, thu, fri, sat;
Bahasa Q menyediakan pendukung khusus untuk type penyebutan satu per satu (enumeration types) (mencakup type Built-In Bool, dan juga type Char), atas dasar operasi berikut :
• Anggota dari suatu type penyebutan satu per satu (enumeration types) dapat dibandingkan
menggunakan operator relational (cf. Bagian 6.4.4 [Operator Relational], halaman 43), mengumpamakan order/pesanan di mana constants/konstanta didaftarkan di dalam deklarasi type. Sebagai contoh, diberikan deklarasi di atas dari type Day, kita mempunyai sun < mon => true.
• Fungsi Succ dan fungsi pred (lihat Bagian 10.1 [Fungsi Perhitungan (Arithmetic Functions )], halaman 93) menghasilkan pengganti/successor dan pendahulu/predecessor dari anggota suatu type penyebutan satu per satu (enumeration type). E.G., succ sun => mon.
• Fungsi Ord (lihat Bagian 10.4 [Fungsi Konversi (Conversion Functions)], halaman 95) menghitung nomor urut jumlah dari anggota suatu type penyebutan satu per satu (enumeration type). E.G., ord sun => 0.
• Operator ‘+’ Dan ‘-’ dapat digunakan untuk melaksanakan perhitungan sederhana pada
anggota type penyebutan satu per satu (enumeration type). Jika X adalah suatu anggota penyebutan satu per satu (enumeration type) kemudian X+N dan X-N menghasilkan Nth pengganti/successor dan pendahulu/predecessor X, berturut-turut. E.G., mon+3 => thu dan fri-5 => sun.
Ini juga bekerja dengan angka-angka negatif: fri+(-3) => tue. Lebih dari itu, jika X dan Y adalah anggota dari type enumeration yang sama maka X-Y menghasilkan perbedaan ord X-ord Y dari bilangan tingkat yang bersesuaian. Dengan begitu, e.g., fri-tue => 3.
• Fungsi Enum dan enum_from dapat digunakan untuk membangun/construct suatu list terdiri
dari suatu range dari nilai-nilai type penyebutan satu per satu (enumeration type). Beberapa notasi stenografi menyenangkan seperti [X..Y] disajikan juga, lihat di bawah untuk detil.
Catat bahwa selama tidak ada operasi langsung untuk mengubah bilangan ordinal kembali ke anggota yang bersesuaian dari suatu type yang diberi, kamu dapat dengan mudah memenuhi ini menggunakan perhitungan:
==> ord thu 4
==> sun+4 thu
Type penyebutan satu per satu (enumeration type) perhitungan juga menyediakan suatu cara cepat untuk memeriksa apakah dua anggota type penyebutan satu per satu (enumeration type) kepunyaan type yang sama:
true
Di sini kita mempekerjakan fungsi standard library isint untuk menentukan apakah perbedaan nomor urut dari dua nilai-nilai adalah benar-benar suatu bilangan bulat/integer. Pekerjaan ini
karena operator ‘-’ akan gagal jika kedua constants/konstanta memiliki ke type penyebutan satu per satu (enumeration types) berbeda.
Penggunaan “penyebutan satu per satu (enumerations)” (yang diuraikan secara detil di bawah),
kamu dapat juga mendaftar semua anggota type penyebutan satu per satu (enumeration types) yang dimulai pada nilai yang ditentukan sebagai berikut:
==> [sun..]
[sun,mon,tue,wed,thu,fri,sat]
Mari kita sekarang mengambil lebih mendalam pada penyebutan satu per satu (enumerations). Operasi pusat untuk menciptakan suatu (enumeration) penyebutan satu per satu adalah fungsi builtin enum, yang mendaftarkan semua anggota dari suatu type penyebutan satu per satu (enumeration types) di dalam range/cakupan yang ditentukan:
==> enum mon fri [mon,tue,wed,thu,fri]
Fungsi Enum_From bekerja seperti enum, tetapi hanya mengambil argument tunggal dan list semua anggota dari type yang dimulai pada nilai yang diberikan:
==> enum_from mon
[mon,tue,wed,thu,fri,sat]
Catat bahwa default “ukuran langkah (step size)” adalah 1. Suatu ukuran langkah arbitary dapat
ditandai/diindikasikan dengan menggunakan enum atau enum_from dengan dua anggota awal di argument pertama sebagai berikut:
==> enum [sun,tue] sat [sun,tue,thu,sat] ==> enum [sat,fri] sun
[sat,fri,thu,wed,tue,mon,sun] ==> enum_from [sun,tue]
[sun,tue,thu,sat]
==> enum_from [sat,fri]
[sat,fri,thu,wed,tue,mon,sun]
Notasi [X1,X2,...,Xn..Y] disajikan sebagai “syntactic sugar” untuk enum [X1,X2,...,Xn]
Y, maka kamu dapat juga tulis sebagai berikut:
==> [mon..fri] [mon,tue,wed,thu,fri] ==> [sun,tue..sat] [sun,tue,thu,sat] ==> [sat,fri..sun] [sat,fri,thu,wed,tue,mon,sun]
==> [mon..] [mon,tue,wed,thu,fri,sat] ==> [sun,tue..] [sun,tue,thu,sat] ==> [sat,fri..] [sat,fri,thu,wed,tue,mon,sun]
Kita menyebutkan bahwa type built-in Char adalah juga suatu type penyebutan satu per satu (enumeration type), yang terdiri dari semua karakter di dalam set karakter yang Unicode. Dengan begitu perhitungan pada karakter bekerja seeperti yang diharapkan:
==> "a"+5 "f" ==> "z"-2 "x" ==> "8"-"0" 8
Operasi enum juga berlaku untuk karakter maka:
==> enum "a" "k" ["a","b","c","d","e","f","g","h","i","j","k"] ==> ["a".."k"] ["a","b","c","d","e","f","g","h","i","j","k"] ==> ["k","j".."a"] ["k","j","i","h","g","f","e","d","c","b","a"]
Operasi Enum_From bekerja dengan Char, juga, tetapi ini pada umumnya agak sia-sia sebab set karakter yang Unicode adalah cukup besar dan dengan begitu adalah agak tidak efisien untuk membangun suatu list lengkap dari semua karakter yang dimulai pada nilai yang ditentukan. Cara benar yang akan bekerja bersama karakter yang sangat besar penyebutan satu per satu
(enumeration type) seperti itu akan mengambil keuntungan dari evaluasi “lazy” dan
menggunakan suatu penyebutan satu per satu (enumeration) stream sebagai gantinya, lihat di bawah.
Pembuka standard (lihat Bab 11 [Standard library], halaman 113) meluaskan succ, pred dan enum (tetapi bukan enum_from, untuk pertimbangan jelas nyata) untuk integer/bilangan bulat, yang secara efektif memutar integer/bilangan bulat ke dalam suatu (sekalipun hanya tanpa batas/albeit infinite) type penyebutan satu per satu (enumeration type):
==> succ 0 1 ==> pred 0 -1 ==> [0..9] [0,1,2,3,4,5,6,7,8,9] ==> [0,2..9] [0,2,4,6,8]
==> [9,8..0]
[9,8,7,6,5,4,3,2,1,0]
Pembuka standard juga mengimplementasikan enum (tetapi bukan succ dan pred) pada nilai- nilai floating point:
==> [0.1,0.2..1.0]
[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]
Catat bahwa ini juga memungkinkan untuk memohon enum atau enum_from dengan lebih dari dua anggota di argument pertama. Itu adalah, kamu dapat membangun penyebutan satu per satu (enumerations) dengan lebih dari dua anggota awal. Tidak interpreter maupun library menyediakan definisi manapun untuk ini, maka terserah anda untuk memperkenalkan penafsiran milikmu seperti constructs/pembangun itu ketika kamu memerlukannya. Sebagai contoh:
[X1,X2,X3..Y] = while (<=Y) (F*) X1 if (F>1) and then (Z3=X3) where F:Int = X2 div X1, Z3:Int = X2*F;
Definisi ini mempekerjakan fungsi standard library selama untuk membangun suatu peningkatan geometris rangkaian/seri integer/bilangan bulat jika [itu] mendeteksi suatu rasio/perbandingan bilangan bulat constant/tetap antara tiga anggota awal:
==> [2,4,8..128] [2,4,8,16,32,64,128]
Pembuka standard juga menyediakan penyebutan satu per satu (enumerations) untuk list “lazy”
a.k.a. stream, cf. Bagian 11.7 [Stream], halaman 126. Fungsi Streamenum dan streamenum_from bekerja seperti enum dan enum_from, berturut-turut, tetapi membangun stream sebagai ganti list. Dalam kasus streamenum_from, stream yang diproduksi mungkin
adalah tanpa batas. Bahasa Q menyediakan jenis yang sama dari “syntactic sugar” untuk stream
penyebutan satu per satu (enumerations) seperti untuk lists, satu-satunya perbedaan adalah kurung kurawal yang digunakan sebagai ganti tanda-kurung. Sebagai contoh, {1..9} menandakan suatu stream terdiri dari suatu urutan perhitungan terbatas, selama {0..} adalah stream yang tidak terbatas dari semua bilangan bulat/integer nonnegative.
Oleh karena evaluasi “lazy”, streamenum_from dapat sering digunakan untuk bekerja di sekitar
ketidakcakapan enum_from manakala kamu harus berhadapan dengan penyebutan satu per satu karakter sangat besar (huge enumerations). Sebagai contoh, di sini adalah bagaimana kita dapat menggunakan suatu stream penyebutan satu per satu (stream enumeration) untuk menghitung banyaknya semua karakter Unicode alfabet:
==> #filter isalpha {chr 1..} 90342
Ini akan mengambil sedikit while, tetapi pekerjaan o.k. sebab kita tidak pernah benar-benar membangun list lengkap semua karakter Unicode, sebagaimana kasus ketika melakukan yang sama dengan list penyebutan satu per satu (list enumerations).