Mojo menata kode yang dapat digunakan ulang melalui dua unit, yaitu modul dan package. Modul adalah satu berkas .mojo yang memuat fungsi, struct, atau konstanta, sedangkan package adalah direktori berisi beberapa modul yang disatukan oleh berkas __init__.mojo. Topik ini membahas cara membuat keduanya, cara menulis import yang benar dari sisi pemakai, dan cara mengubah package menjadi paket precompiled berupa berkas .mojoc dengan perintah mojo precompile. Seluruh contoh berada pada satu direktori dan dijalankan dengan mojo run, sehingga hubungan antara berkas sumber dan nama yang diimpor dapat ditelusuri sampai ke keluarannya.
Modul sebagai unit import terkecil#
Modul dalam Mojo adalah berkas .mojo tunggal yang isinya dapat diimpor oleh berkas lain tanpa konfigurasi tambahan. Berkas geometri.mojo berikut memuat dua fungsi biasa, dan nama modulnya adalah geometri, sesuai nama berkasnya.
def luas_persegi(sisi: Int) -> Int:
return sisi * sisi
def keliling_persegi(sisi: Int) -> Int:
return 4 * sisiDi sisi pemakai, fungsi yang dibutuhkan diimpor melalui pernyataan from ... import, lalu dipanggil seperti fungsi lokal. Berkas pakai-geometri.mojo berada di direktori yang sama dengan geometri.mojo, sehingga pencarian modulnya langsung berhasil.
from geometri import luas_persegi, keliling_persegi
def main():
print(luas_persegi(5))
print(keliling_persegi(5))# modul geometri dicari pada direktori yang sama
mojo run pakai-geometri.mojo25
20Keluaran 25 adalah luas persegi bersisi lima, sedangkan 20 adalah kelilingnya. Tidak ada langkah registrasi atau berkas konfigurasi yang diperlukan, karena penamaan modul mengikuti nama berkas secara langsung. Konvensi ini berlaku untuk semua program Mojo, termasuk program yang nantinya memakai package.
Satu modul sebaiknya menampung satu tanggung jawab, dan contoh pada topik ini mengikuti kebiasaan tersebut. Modul geometri hanya menyimpan fungsi bangun datar, sedangkan fungsi ringkasan angka berada pada package terpisah yang dibahas di bawah. Pemisahan semacam ini membuat pencarian fungsi cepat karena nama modul langsung menggambarkan isinya, dan perubahan satu tanggung jawab tidak menyentuh berkas tanggung jawab lain.
Package: direktori dengan init.mojo#
Package mengelompokkan beberapa modul ke dalam satu direktori yang wajib memuat berkas __init__.mojo, sehingga direktori itu dapat diimpor sebagai satu nama. Struktur direktori contoh pada topik ini terlihat seperti berikut.
├── geometri.mojo
├── pakai-geometri.mojo
├── pakai-statistik.mojo
├── pakai-artefak.mojo
└── statistik/
├── __init__.mojo
└── ringkas.mojoDirektori statistik adalah sebuah package yang memuat satu modul bernama ringkas. Isi modul tersebut adalah dua fungsi statistik sederhana.
def rata_rata(nilai: List[Float64]) -> Float64:
var total = 0.0
for x in nilai:
total += x
return total / Float64(len(nilai))
def maksimum(nilai: List[Float64]) -> Float64:
var terbesar = nilai[0]
for x in nilai:
if x > terbesar:
terbesar = x
return terbesarBerkas __init__.mojo menentukan nama yang tampak di sisi import. Barisnya memindahkan rata_rata dan maksimum dari modul ringkas ke ruang nama package, sebuah teknik yang disebut re-export.
from .ringkas import rata_rata, maksimumDengan re-export tersebut, pemakai mengimpor langsung dari nama package tanpa perlu tahu modul di dalamnya.
from statistik import rata_rata, maksimum
def main():
var nilai: List[Float64] = [7.5, 8.0, 6.5, 9.0]
print(rata_rata(nilai))
print(maksimum(nilai))# package statistik diimpor lewat nama hasil re-export
mojo run pakai-statistik.mojo7.75
9.0Import langsung ke modul di dalam package juga sah, seperti bentuk from statistik.ringkas import rata_rata berikut. Bentuk ini berguna apabila dua modul dalam satu package memuat nama yang sama dan pemakai ingin memilih sumbernya secara eksplisit.
# tidak-dijalankan
from statistik.ringkas import rata_rataPaket precompiled dengan mojoc#
Perintah mojo precompile mengubah package menjadi paket precompiled berupa satu berkas .mojoc, sehingga import tidak lagi membaca ulang seluruh berkas sumber di dalamnya. Nama berkas pada opsi -o menentukan nama modul yang diimpor pemakai, dan nama tersebut boleh berbeda dari nama direktori sumbernya. Artefaknya diletakkan pada direktori proyek dan langsung menjadi bagian pencarian import.
Manfaat utamanya muncul saat package berisi banyak berkas, karena bantuan resminya menyebut paket precompiled lebih cepat dipakai oleh build dibandingkan membangunnya dari sumber. Konsekuensinya, setiap perubahan isi package menuntut precompile ulang agar artefaknya ikut berubah. Untuk package sekecil statistik di sini, manfaatnya lebih berupa kebiasaan kerja yang rapi, sedangkan keuntungan performanya baru terasa pada package yang terus membesar.
# precompile package statistik menjadi artefak bernama laporan
mojo precompile statistik -o laporan.mojocPerintah di atas tidak mencetak apa pun ketika berhasil, dan berkas laporan.mojoc muncul di direktori proyek. Karena artefak dinamai laporan, berkas pemakainya mengimpor dari nama tersebut.
from laporan import rata_rata
def main():
var nilai: List[Float64] = [7.5, 8.0, 6.5, 9.0]
print(rata_rata(nilai))# import mengikuti nama artefak pada opsi -o
mojo run pakai-artefak.mojo7.75Bantuan resmi mojo precompile mencatat dua batasan yang patut diingat. Artefak .mojoc terikat pada versi compiler yang menghasilkannya, sehingga memuat artefak dengan versi compiler yang berbeda akan error, dan format ini bukan format distribusi untuk pengguna akhir. Selain itu, subperintah lama mojo package kini berstatus deprecated, yaitu masih berjalan tetapi menyuruh penggunanya beralih ke mojo precompile.
Kesalahan umum#
Tiga kesalahan berikut paling sering muncul saat menata package pada Mojo. Masing-masing disertai penyebab dan perbaikannya.
- Import ditulis sebelum artefak dibuat, atau nama yang diimpor tidak cocok dengan opsi
-o. Compiler menolak berkasnya dengan pesanerror: unable to locate module 'laporan'pada baris importnya. Perbaikannya adalah menjalankanmojo precompile statistik -o laporan.mojocterlebih dahulu, atau menyamakan nama pada opsi-odengan nama yang diimpor. - Subperintah
mojo packagedipakai karena kebiasaan lama. Perintah ini masih menghasilkan berkas, tetapi setiap pemanggilannya mencetak peringatan'package' is deprecated; use 'precompile' instead. Perbaikannya adalah mengganti seluruh pemanggilan denganmojo precompile. - Berkas
.mojocdipindahkan ke lingkungan dengan versi compiler yang berbeda. Artefak hanya dijamin dimuat dengan benar oleh versi compiler yang sama, sehingga perbaikannya adalah menjalankanmojo precompileulang di lingkungan target.
Ringkasan#
- Modul adalah berkas
.mojotunggal, dan importnya ditulisfrom geometri import luas_persegisesuai nama berkasnya. - Package adalah direktori dengan
__init__.mojo, danfrom .ringkas import rata_ratadi dalamnya membuat fungsi dapat diimpor langsung dari nama package. mojo precompile statistik -o laporan.mojocmenghasilkan paket precompiled yang diimpor sesuai nama pada opsi-o, dengan syarat versi compiler sama.
Referensi#
- Mojo modules and packages — Mojo Manual
— Bagian resmi tentang modul, package, dan paket precompiled yang juga dirujuk perintah
mojo precompile. - Mojo Manual — Modular — Panduan resmi bahasa Mojo yang menjadi acuan struktur import pada topik ini.