Odin membundel pustaka standar (standard library) bernama core bersama compilernya. Pustaka ini berupa kumpulan paket untuk kebutuhan umum, mulai dari pemrosesan teks, perhitungan numerik, akses lingkungan proses, pengukuran waktu, hingga struktur data. Topik ini meninjau lima kelompok paket yang paling sering dipakai, yaitu core:strings, core:math, core:os, core:time, dan core:container, bersama dua program contoh dan keluarannya. Setelah membaca topik ini, paket yang tepat untuk setiap kebutuhan dapat ditentukan, proc utamanya dapat dipanggil dengan tanda tangan (signature) yang benar, dan dokumentasinya dapat ditelusuri lebih jauh.
Menemukan dan mengimpor paket core#
Paket core terpasang di samping compiler dalam bentuk kode sumber yang dapat dibaca. Setiap paket diimpor dengan akar jalur core:, misalnya import "core:strings" untuk paket teks dan import "core:math" untuk paket matematika. Nama yang dipakai di dalam kode mengikuti bagian terakhir jalur import tersebut, sehingga pencarian substring ditulis sebagai strings.contains dan bukan contains tanpa awalan. Aturan yang sama berlaku untuk subpackage, seperti import "core:container/queue" yang seluruh procnya diakses melalui nama queue.
Dokumentasi resmi seluruh paket core berada di pkg.odin-lang.org dengan satu halaman per paket. Halaman tersebut memuat tanda tangan setiap proc beserta penjelasan parameternya, sehingga menjadi tempat pertama untuk memastikan nama proc dan urutan parameternya. Berkas sumbernya juga dapat dibaca langsung karena ikut terpasang bersama compiler, sehingga perilaku yang diragukan dapat ditelusuri sampai implementasinya.
Tabel berikut merangkum kelima paket yang dibahas pada topik ini.
| Paket | Kegunaan | Contoh proc |
|---|---|---|
core:strings | Pencarian, pemangkasan, dan pemisahan teks | strings.contains, strings.fields, strings.split, strings.trim_space |
core:math | Konstanta matematika dan fungsi numerik | math.sin, math.sqrt, math.pow |
core:os | Argumen proses, kode keluar, dan pembacaan berkas | os.args, os.exit, os.read_entire_file |
core:time | Menyatakan durasi, memperoleh waktu, dan menjalankan jeda | time.now, time.sleep, time.diff |
core:container | Struktur data tambahan di luar bawaan bahasa | queue.Queue, queue.push_back, queue.pop_front |
core:strings untuk pemrosesan teks#
Paket core:strings menyediakan operasi yang bekerja pada tipe string bawaan bahasa. Proc strings.contains mengembalikan nilai bool yang menyatakan apakah sebuah substring muncul di dalam string, sedangkan strings.trim_space menghilangkan karakter whitespace ASCII di awal dan akhir string. Hasil trim_space berupa potongan dari string aslinya, sehingga kedua proc ini tidak melakukan alokasi memori sama sekali.
Dua proc berikutnya mengembalikan slice string baru sehingga membutuhkan alokasi. Proc strings.fields memisahkan string menjadi kata-kata pada setiap rentang whitespace dan mengabaikan elemen kosong, sedangkan strings.split memisahkan string pada setiap kemunculan pemisah tertentu. Perbedaannya terlihat pada pemisah yang berdampingan, karena split tetap menghasilkan elemen kosong di antaranya, sedangkan fields tidak. Keduanya mengalokasikan hasil melalui alokator (allocator) context.allocator secara default, sehingga slice hasilnya dihapus dengan delete ketika sudah tidak dipakai.
Keempat proc ini dipakai pada program contoh di bagian berikutnya untuk membaca berkas data sensor suhu, memisahkannya menjadi baris, lalu memecahnya menjadi angka.
core:math untuk perhitungan numerik#
Paket core:math memuat konstanta matematika dan fungsi numerik dasar. Konstanta math.PI, math.TAU, dan math.E dideklarasikan sebagai konstanta untyped, sehingga nilainya beradaptasi dengan tipe titik-mengambang (floating point) yang membutuhkannya. Karena itu, ekspresi math.PI / 3 yang dikirim ke math.sin menjadi nilai f64 tanpa konversi manual.
Proc seperti math.sin, math.cos, math.sqrt, dan math.pow merupakan kelompok proc (procedure group) yang berisi varian untuk tipe f16 hingga f64. Compiler memilih varian yang sesuai berdasarkan tipe argumennya, sehingga pemanggilannya tidak memerlukan akhiran tipe. Aturan ini menimbulkan satu jebakan kecil, yaitu pemanggilan math.sqrt(144) ditolak karena bilangan bulat untyped cocok dengan lebih dari satu varian, sedangkan math.sqrt(f64(144)) dan math.sqrt(144.0) diterima karena tipenya sudah jelas.
Paket ini juga menyediakan pembulatan seperti math.floor dan math.ceil, serta perangkat untuk nilai khusus titik-mengambang seperti NaN dan tak hingga yang dikelompokkan dalam enum Float_Class. Keluaran program contoh menampilkan hasil sin(pi/3) dengan empat desimal melalui verb %.4f milik paket fmt.
core:os untuk lingkungan proses#
Paket core:os menyediakan akses ke lingkungan proses, yaitu argumen baris perintah, berkas, direktori, variabel lingkungan, dan penghentian program. Nama os.args merupakan variabel di tingkat paket bertipe []string, bukan proc, sehingga jumlah argumennya diambil dengan len(os.args). Elemen pertamanya berisi jalur program yang dijalankan, sedangkan argumen tambahan dari pengguna menyusul setelahnya.
Pembacaan berkas disediakan oleh os.read_entire_file, kelompok proc yang membaca seluruh isi berkas ke dalam slice []byte dan mengembalikan dua nilai, yaitu data serta pesan error. Parameter kedua os.read_entire_file adalah alokator yang digunakan untuk menyimpan data, sehingga pemanggilannya diakhiri dengan context.allocator. Nilai error wajib diperiksa sebelum data dipakai karena berkas dapat hilang atau tidak dapat dibaca.
Proc os.exit menghentikan proses secara langsung dan tidak pernah kembali ke pemanggilnya, sifat yang dalam Odin dinyatakan dengan tipe kembalian -> !. Nilai yang dikirim menjadi kode keluar (exit code) yang diterima shell. Pada program contoh, os.exit dipanggil di dalam percabangan error untuk menghentikan program dengan kode 1 apabila berkas data tidak dapat dibaca.
core:time untuk waktu dan jeda#
Paket core:time menangani waktu saat program berjalan dan jeda eksekusi. Durasi dinyatakan dengan tipe Duration, tipe distinct di atas bilangan bulat 64-bit yang menyimpan nanodetik, beserta konstanta bantu dari time.Nanosecond sampai time.Hour. Konstanta ini membuat jeda ditulis secara eksplisit, misalnya time.sleep(time.Second) untuk berhenti selama satu detik.
Waktu saat ini diperoleh dari time.now yang mengembalikan nilai Time berpresisi nanodetik sejak epoch UNIX. Selisih dua waktu dihitung dengan time.diff yang menerima waktu awal dan waktu akhir, sedangkan time.since menyediakan bentuk singkatnya terhadap waktu sekarang. Keduanya mengembalikan Duration, sehingga perbandingan seperti durasi >= time.Second dapat ditulis langsung tanpa konversi.
Pengukuran seperti itu bergantung pada saat eksekusi, sehingga nilainya berubah setiap program dijalankan. Karena itu, program contoh tidak mencetak durasi mentahnya, melainkan membandingkan hasil pengukuran dengan time.Second dan mencetak nilai bool yang stabil. Paket ini juga menyediakan Stopwatch untuk menjumlahkan waktu dari beberapa kali pengukuran tanpa menghitung selisih waktu secara manual.
Program contoh yang menggabungkan empat paket#
Program berikut mempraktikkan core:os, core:strings, core:math, dan core:time dalam satu proc main. Program membaca berkas data sensor suhu yang berada di direktori yang sama, memisahkannya menjadi baris dan angka, menjalankan dua perhitungan matematika, lalu mengukur jeda satu detik. Berkas datanya berisi lima pembacaan suhu dalam dua baris. Hasil pembacaan berupa []byte dikonversi menjadi teks dengan string(data), konversi yang hanya membungkus byte tanpa menyalinnya. Memori alokasinya dibebaskan oleh defer delete(data) ketika proc main berakhir.
23.5 24.1 22.8
25.0 23.9package main
import "core:fmt"
import "core:math"
import "core:os"
import "core:strings"
import "core:time"
main :: proc() {
fmt.printf("Jumlah argumen: %d\n", len(os.args))
data, err := os.read_entire_file("sensor-suhu.txt", context.allocator)
if err != nil {
fmt.println("Gagal membaca berkas:", err)
os.exit(1)
}
defer delete(data)
teks := strings.trim_space(string(data))
fmt.println("Baris:", strings.split(teks, "\n"))
nilai := strings.fields(teks)
fmt.println("Pembacaan:", nilai)
fmt.println("Mengandung 24.1:", strings.contains(teks, "24.1"))
sudut := math.PI / 3
fmt.printf("sin(pi/3) = %.4f\n", math.sin(sudut))
fmt.printf("sqrt(144) = %.2f\n", math.sqrt(f64(144)))
awal := time.now()
time.sleep(time.Second)
fmt.printf("Jeda >= 1 detik: %v\n", time.diff(awal, time.now()) >= time.Second)
}# mengompilasi dan menjalankan program contoh
odin run main.odin -file
# menampilkan kode keluar proses yang baru saja selesai
echo "Kode keluar: $?"Jumlah argumen: 1
Baris: ["23.5 24.1 22.8", "25.0 23.9"]
Pembacaan: ["23.5", "24.1", "22.8", "25.0", "23.9"]
Mengandung 24.1: true
sin(pi/3) = 0.8660
sqrt(144) = 12.00
Jeda >= 1 detik: true
Kode keluar: 0Urutan keluarannya sama dengan urutan kode. Jumlah argumen bernilai satu karena elemen pertama os.args adalah jalur program itu sendiri. Pembacaan berkas menghasilkan slice per baris melalui strings.split dan slice per angka melalui strings.fields, sedangkan baris jeda berasal dari perbandingan durasi dengan time.Second yang selalu bernilai true untuk jeda minimal satu detik. Perintah echo pada blok bash menampilkan kode keluar program, yang bernilai 0 karena percabangan error tidak terjadi dan program berakhir secara normal.
core:container dan struktur data bawaan bahasa#
Struktur data yang paling sering dipakai di Odin tidak membutuhkan paket apa pun karena sudah menjadi bagian bahasanya. Tipe map menyediakan kamus kunci-nilai, sedangkan bit_set menyediakan himpunan bertanda bit, dan keduanya tidak membutuhkan import. Paket core:container berada di lapisan di atasnya, yaitu kumpulan struktur data yang implementasinya membutuhkan kode pustaka.
Pada versi compiler yang dipakai di jalur ini, paket untuk kelompok struktur data tersebut bernama core:container dan terbagi menjadi subpackage seperti queue, priority_queue, rbtree, dan lru. Nama core:collections yang lazim pada pustaka bahasa lain tidak ada di Odin, sehingga penelusuran dokumentasinya dilakukan melalui nama container. Subpackage queue menyediakan Queue, antrean generik berkapasitas dinamis yang menambahkan elemen di belakang dengan queue.push_back dan mengeluarkan elemen tertua dari depan dengan queue.pop_front.
Program kedua mempraktikkan subpackage tersebut dengan contoh antrean tiket loket. Variabel q dideklarasikan sebagai queue.Queue(string) dan langsung siap dipakai karena nilai kosongnya sudah valid. Tiga tiket ditambahkan lalu dikeluarkan berurutan, sedangkan queue.len menghitung sisa antrean pada setiap iterasi.
package main
import "core:container/queue"
import "core:fmt"
main :: proc() {
q: queue.Queue(string)
queue.push_back(&q, "tiket 101")
queue.push_back(&q, "tiket 102")
queue.push_back(&q, "tiket 103")
for queue.len(q) > 0 {
berikut := queue.pop_front(&q)
fmt.printf("Melayani %s\n", berikut)
}
fmt.printf("Sisa antrean: %d\n", queue.len(q))
}# menjalankan program antrean
odin run antrean.odin -fileMelayani tiket 101
Melayani tiket 102
Melayani tiket 103
Sisa antrean: 0Urutan keluarannya sama dengan urutan masukan, sesuai sifat antrean first in, first out (FIFO). Subpackage lain pada core:container mengikuti pola yang sama, misalnya priority_queue yang mengeluarkan elemen menurut fungsi perbandingan yang disediakan penggunanya alih-alih menurut urutan masuk.
Kesalahan umum: pernyataan sesudah os.exit#
Karena os.exit tidak pernah kembali ke pemanggilnya, pernyataan yang ditulis setelahnya tidak mungkin dieksekusi. Compiler Odin menolak kode seperti itu pada saat kompilasi dengan pesan error yang menyebut pemanggilan divergen (diverging), bukan membiarkannya sebagai kode mati yang diam-diam tidak pernah dijalankan. Sifat ini membantu penulis menemukan kesalahan urutan sejak program belum dijalankan. Kesalahan semacam ini biasanya muncul ketika jalur keluar cepat ditambahkan di tengah proc untuk pengujian, lalu pernyataan pencetakan tambahan ditulis di bawahnya tanpa disadari.
Error terjadi pada saat kompilasi, sehingga pemeriksaannya memakai odin check tanpa perlu menjalankan program. Kesalahan berikut dibuat, diperiksa, lalu berkasnya dihapus untuk menunjukkan pesan errornya.
# membuat berkas yang memuat pernyataan sesudah os.exit
cat > keluar-gagal.odin <<'EOF'
package main
import "core:fmt"
import "core:os"
main :: proc() {
fmt.println("Baris pertama")
os.exit(0)
fmt.println("Baris ini tidak pernah dicetak")
}
EOF
# memeriksa berkas, lalu menghapusnya
odin check keluar-gagal.odin -file
rm keluar-gagal.odin/home/kal/my-project/content/odin/paket-dan-pustaka/pustaka-core/keluar-gagal.odin(8:2) Error: Statements after a diverging procedure call are never executed
os.exit(0)
^~~~~~~~~^ Pesan error menunjuk baris 8 kolom 2, tepat pada pemanggilan os.exit(0) yang memisahkan pernyataan sebelum dan sesudahnya. Perbaikannya berupa pemindahan pernyataan yang masih diperlukan ke sebelum pemanggilan os.exit, atau pemanggilan os.exit di dalam percabangan sebagaimana pola penanganan error pada program contoh. Setelah berkas keluar-gagal.odin dihapus, direktori topik kembali hanya berisi berkas yang dirujuk.
Ringkasan#
- Pustaka core terpasang bersama compiler dalam bentuk kode sumber, diimpor dengan akar
core:, dan didokumentasikan satu halaman per paket di pkg.odin-lang.org. - core:strings menyediakan
contains,trim_space,fields, dansplit, denganfieldssertasplitmengalokasikan hasilnya melalui alokator konteks. - core:math memuat konstanta
PIdan kelompok procsinsertasqrtyang menyesuaikan tipe argumennya, sedangkan core:os menyediakanargssebagai variabel paket,read_entire_filedengan pemeriksaan error, danexityang divergen. - core:time bekerja dengan
Durationnanodetik beserta procnow,sleep, dandiff, sedangkan struktur data tambahan berada di core:container sepertiqueue.Queuedenganpush_backdanpop_front.
Referensi#
- Odin Documentation Overview — odin-lang.org — Panduan resmi bahasa Odin yang menjelaskan package, import, map, dan fitur bahasa yang dipakai bersama pustaka core.
- Referensi paket Odin — pkg.odin-lang.org — Indeks halaman dokumentasi resmi untuk seluruh paket core, termasuk lima paket yang dibahas pada topik ini.