Nim menjalankan sebagian kode pada waktu kompilasi, jauh sebelum program dijalankan, dan mekanismenya tersebar dalam empat bentuk yang saling melengkapi. Konstanta const dihitung sekali saat kompilasi, pernyataan when memilih cabang kode menurut kondisi yang sudah pasti, parameter static menuntut argumen yang diketahui saat kompilasi, dan blok static menjalankan pernyataan apa saja pada saat kompilasi. Topik ini mempraktikkan keempatnya dan menunjukkan batas yang menjaga kepastian semuanya, yaitu nilai waktu kompilasi wajib bisa dihitung tanpa program yang sudah berjalan.
Konstanta const dihitung sekali#
Konstanta dinyatakan dengan const, dan ekspresinya wajib dapat dihitung saat kompilasi karena hasilnya disematkan langsung ke program. Perhitungan yang mahal sekali pun hanya dibayar sekali pada waktu kompilasi, dan pembacaannya saat program berjalan sama cepatnya dengan membaca nilai tetap.
# const dihitung sekali pada waktu kompilasi
const detikPerHari = 24 * 60 * 60
const mebiBita = 1024 * 1024
const modeDebug = false
echo detikPerHari
echo mebiBita
echo modeDebug# kompilasi dan jalankan program konstanta waktu kompilasi
nim r -f --hints:off konstanta.nim86400
1048576
falseTiga nilai itu sudah jadi di dalam berkas biner sebelum program sempat berjalan, sehingga ekspresi seperti 24 * 60 * 60 tidak menyisakan perkalian pada saat berjalan. Kebiasaan yang baik menaruh konstanta terkait konfigurasi di satu modul tersendiri, karena konstanta yang dihitung dari konstanta lain juga dihitung berantai pada waktu kompilasi. Ekspresi penghitungnya bahkan boleh memanggil proc biasa, karena kompilator menjalankannya pada penafsir waktu kompilasi, sehingga nilai seperti deret Fibonacci untuk indeks tertentu dapat dihitung sekali di waktu kompilasi dan menjadi tetapan di dalam biner.
Posisi const di antara tiga pernyataan penyimpanan nilai menjadi lebih jelas ketika diletakkan berdampingan. var menyimpan nilai yang dapat berubah dan hidup di memori saat program berjalan, let menyimpan nilai tetap setelah diisi sekali pada waktu berjalan, sedangkan const menuntut nilainya sudah jadi sebelum program ada, dan pemilihan yang tepat sejak awal menjaga batas antara konfigurasi dan keadaan program tetap rapi.
when memilih cabang pada waktu kompilasi#
Pernyataan when menyerupai if, tetapi kondisinya wajib bernilai pasti saat kompilasi dan hanya cabang yang terpilih yang masuk program. Cabang yang tidak terpilih bahkan tidak diperiksa kompilatornya, sehingga kode khusus satu platform boleh memakai pengenal yang tidak ada di platform lain.
# when memilih cabang kode pada waktu kompilasi
const modeDebug = false
when modeDebug:
echo "mode debug aktif"
else:
echo "mode debug nonaktif"
when defined(windows):
echo "platform: windows"
elif defined(linux):
echo "platform: linux"
else:
echo "platform tidak dikenal"# kompilasi dan jalankan pemilihan cabang waktu kompilasi
nim r -f --hints:off pilihan_when.nimmode debug nonaktif
platform: linuxSandbox ini berjalan di Linux, sehingga cabang defined(windows) tidak masuk program sama sekali, dan pada mesin Windows justru cabang pertamalah yang terpilih dengan keluaran platform: windows. Perbedaannya dengan if mendasar, yaitu if mengeksekusi salah satu cabang saat program berjalan dan seluruh cabangnya wajib sah, sedangkan when memangkas pohon kode sebelum kompilasi berlangsung. Identifikasi platform pada contoh memakai defined(windows) dan defined(linux), dan kondisi waktu kompilasi lain dapat memakai konstanta bawaan seperti nimMajor yang nilainya bertambah pada setiap rilis Nim, sehingga kode yang memanfaatkan fitur baru dapat memberi jalan bagi versi lama tanpa memecah berkasnya.
Perbedaan itu juga menjadikan when teman dekat parameter static, karena keduanya memakai nilai yang sama pastinya, yaitu kondisi yang telah selesai dihitung sebelum baris program pertama dijalankan.
Parameter static dan blok static#
Tipe parameter static[T] menuntut argumen yang diketahui saat kompilasi, dan argumen itu menjadi bagian tipe proc sehingga setiap nilai memunculkan instansiasi tersendiri. Bentuk ini adalah fondasi proc generik yang perilakunya bergantung nilai konstanta, misalnya ukuran larik tetap. Blok static melengkapi keduanya dengan menjalankan pernyataan saat kompilasi dan mencetak hasilnya sebelum program ada.
# Parameter static dan blok static pada waktu kompilasi
proc duaPangkat[n: static int](x: float): float =
var hasil = 1.0
for i in 1 .. n:
hasil *= x
hasil
static:
echo "dihitung saat kompilasi: ", 6 * 7
echo duaPangkat[10](2.0)
echo duaPangkat[3](5.0)# kompilasi dan jalankan parameter static beserta blok static
nim r -f --hints:off static_param.nimdihitung saat kompilasi: 42
1024.0
125.0Baris pertama keluaran tercetak pada waktu kompilasi, dan dua baris berikutnya hasil program, dengan duaPangkat[10] dan duaPangkat[3] menjadi dua proc terpisah yang batas perulangannya sudah tertancap di masing-masing. Bentuk [n] pada pemanggilan menegaskan bahwa nilai itu bagian dari tipe, bukan argumen biasa, dan kompilator menolak pemanggilan yang menuliskannya sebagai argumen biasa di dalam kurung.
Parameter static juga mengubah peran proc yang menerimanya, yaitu satu proc melayani banyak nilai konstanta tanpa kehilangan kepastian batasnya, sebagaimana proc larik tetap pada pustaka standar yang ukurannya dinyatakan saat kompilasi. Kebutuhan serupa pada kode generik dibahas topik generics dengan Tumpukan[T], dan parameter static menambahkan sumbu nilai di samping sumbu tipe yang dimiliki parameterisasi biasa. Argumen n tidak dapat diteruskan dari nilai saat berjalan, karena tipe proc dibentuk saat kompilasi, dan kebutuhan pangkat dengan eksponen dinamis memakai parameter biasa.
Kesalahan umum#
- Menghitung
constdari nilai saat berjalan. Pernyataan sepertivar n = 5diikuticonst ganda = n * 2ditolak denganError: cannot evaluate at compile time: n, karena konstanta wajib terbentuk dari nilai yang sudah pasti saat kompilasi, dan pemecahannya mengubahconstmenjadilet. - Mengira cabang
whenyang tidak terpilih tetap diperiksa. Cabang yang gugur tidak masuk program, sehingga pengenal yang hanya ada di cabang itu tidak menimbulkan error, dan sebaliknya error pada cabang terpilih hanya terlihat setelah pilihan berubah. - Memberi argumen dinamis ke parameter
static. PemanggilanduaPangkat[b](2.0)denganbyang baru diketahui saat program berjalan ditolak kompilator, karena parameter static menjadi bagian tipe proc, dan eksponen dinamis memerlukan parameter biasa.
Ringkasan#
constdihitung sekali pada waktu kompilasi dan disematkan ke program, sehingga perhitungan mahal dibayar di luar waktu berjalan.whenmemilih cabang pada waktu kompilasi dan memangkas cabang lain dari program, berbeda dariifyang mengeksekusi saat program berjalan.- Parameter
static[T]menjadikan nilai konstanta bagian dari tipe proc, sedangkan blokstaticmenjalankan pernyataan apa saja saat kompilasi, dan keduanya menuntut nilai yang pasti sebelum program ada.
Referensi#
- Manual Nim: Const — Nim documentation — Aturan ekspresi konstanta dan batasan waktu kompilasinya.
- Manual Nim: When statement — Nim documentation
— Semantik
whenbeserta perbedaannya denganif. - Manual Nim: Static statement/expression — Nim documentation
— Kontrak blok
staticdan parameterstatic[T].