Mendeklarasikan Shape
shape adalah tipe record dengan field yang bernama dan bertipe:
shape Point {
x: i32,
y: i32,
}
Bagian-bagiannya:
shapemengawali deklarasi.Pointadalah nama tipenya.- Kurung kurawal membungkus daftar field, masing-masing dengan bentuk
name: Type.
Deklarasi itu menambahkan tipe baru bernama Point ke scope yang sedang berlaku. Di mana pun kamu bisa memakai tipe bawaan seperti i32, sekarang kamu juga bisa memakai Point.
Membuat Nilai Shape
Buat sebuah instance dengan ekspresi literal struct:
let point = Point { x: 40, y: 2 }
Literal itu menyebut nama shape dan mengisi setiap field. Setiap field wajib ada, karena Zero tidak diam-diam mengisi field yang hilang dengan nol atau null. Kalau kamu lupa satu field, compiler akan memberitahumu:
{
"code": "FLD002",
"message": "missing field: y",
"line": 4
}
(Kode error persisnya bisa berbeda, tetapi prinsip "tidak ada default implisit" tetap sama.)
Kamu bisa menulis anotasi tipenya secara eksplisit kalau ingin tipenya terlihat:
let point: Point = Point { x: 40, y: 2 }
Membaca Field
Akses field memakai sintaks titik:
let point = Point { x: 40, y: 2 }
let xVal = point.x
let yVal = point.y
point.x membaca field x. Tidak ada method get_x(), karena field adalah data biasa.
Contoh Lengkap
Ini contoh point.0 standar dari repository bahasa ini. Klik Jalankan untuk mencobanya:
Telusuri dari atas:
- Deklarasikan shape
Pointdengan dua fieldi32. - Definisikan fungsi
sumyang menerimaPointdan mengembalikan jumlah kedua field-nya. - Di
main, buat sebuahPoint, panggilsum, lalu bandingkan hasilnya.
Tiga langkah, tiga ide seputar shape (deklarasi, pembuatan, akses), dan satu efek, yaitu check world.out.write(...) di bagian akhir. Perhatikan bahwa sum tidak menyentuh World. Itu fungsi murni atas data, dan signature-nya membuat hal itu jelas.
Shape dengan Field Bersarang
Shape bisa menyimpan nilai bertipe apa pun, termasuk shape lain:
shape Range {
start: i32,
end: i32,
}
shape Segment {
label: String,
range: Range,
}
let seg = Segment {
label: "warmup",
range: Range { start: 0, end: 10 },
}
Akses field bisa dirangkai seperti yang kamu harapkan:
let len = seg.range.end - seg.range.start
Shape Generic
Saat field sebuah shape perlu bisa menerima berbagai tipe, deklarasikan parameter tipe di dalam kurung sudut:
shape Pair<T, U> {
left: T,
right: U,
}
Instance-nya menetapkan parameter itu ke tipe konkret:
let intBytePair: Pair<i32, u8> = Pair { left: 40, right: 2_u8 }
let words: Pair<String, String> = Pair { left: "hello", right: "world" }
Alias tipe bisa menyingkat parameterisasi yang sering dipakai:
type BytePair = Pair<u8, u8>
let bytes: BytePair = Pair { left: 1_u8, right: 2_u8 }
Generic membahas parameter tipe lebih dalam, termasuk pada fungsi, bukan hanya pada shape.
Yang Tidak Dimiliki Shape
Beberapa hal yang mungkin kamu harapkan dari "struct" di bahasa lain, tetapi sengaja tidak disertakan dalam shape:
- Tidak ada method. Deklarasi shape hanyalah data. Perilaku ditulis di fungsi lepas yang menerima shape sebagai parameter. Ini mencerminkan pemisahan data dan efek yang sama dengan yang kamu lihat di fungsi.
- Tidak ada inheritance. Shape tidak bisa memperluas shape lain. Kalau kamu ingin struktur yang sama dipakai bersama, pindahkan ke field bersama atau buat sum type dengan choice.
- Tidak ada constructor atau destructor implisit. Pembuatan nilai dilakukan dengan ekspresi literal struct. Pembersihan bersifat eksplisit: saat standard library menyediakan resource yang perlu dibuang, hal itu dilakukan lewat API bergaya capability, bukan lewat RAII tersembunyi.
- Tidak ada field privat. Semua field sebuah shape bisa diakses oleh kode yang bisa melihat tipe shape itu. Visibilitas berlaku di tingkat tipe, bukan di tingkat field.
Polanya: shape adalah tipe record yang sederhana dan mudah ditebak, dan semua hal lain kamu bangun dari situ.
Kapan Memakai Shape dan Kapan Memakai Choice
Panduan singkat:
- Pakai shape saat sebuah nilai punya semua field ini sekaligus.
Pointselalu punyaxdany. - Pakai choice saat sebuah nilai adalah salah satu dari beberapa alternatif.
Resultadalah antaraokatauerr. - Pakai enum saat alternatifnya tidak membawa data tambahan dan hanya berupa label. Nama hari dalam seminggu, state sederhana.
Ketiga bahan dasar ini, yaitu shape (dan), choice (atau), dan enum (atau tanpa payload), mencakup hampir semua kebutuhan pemodelan data.
Berikutnya: Generic
Kamu sudah melihat Pair<T, U> muncul sekilas. Dokumen berikutnya, generic, menjelaskan cara kerja parameter tipe pada shape maupun fungsi, termasuk pola-pola yang muncul di seluruh standard library Zero.
Pertanyaan yang sering diajukan
Apa itu shape di Zero?
shape adalah product type ala struct di Zero, yaitu record bernama dengan field-field bertipe. Kamu mendeklarasikannya dengan shape Name { field1: T1, field2: T2 }, membuat nilainya dengan Name { field1: v1, field2: v2 }, dan membaca field-nya dengan sintaks titik (value.field1). Shape adalah bahan dasar untuk memodelkan data yang terstruktur.
Bagaimana cara membuat nilai shape?
Pakai ekspresi literal struct yang menyebut nama shape dan mengisi setiap field: let point = Point { x: 40, y: 2 }. Setiap field harus diisi, karena Zero tidak diam-diam memberi nilai default pada field yang hilang. Urutan field di literal tidak harus sama dengan urutan di deklarasi.
Apa bedanya shape dengan class?
Shape adalah data biasa: punya field, tetapi tidak punya method, inheritance, atau constructor implisit. Fungsi yang bekerja dengan sebuah shape menerimanya sebagai parameter secara eksplisit. Pemisahan ini menjaga bahasanya tetap kecil dan membuat biaya membangun atau menyalin shape mudah ditebak, tanpa vtable atau destructor tersembunyi.
Apakah shape bisa generic di Zero?
Bisa. Deklarasikan parameter tipe di dalam kurung sudut: shape Pair<T, U> { left: T, right: U }. Instance-nya menetapkan parameter itu: Pair<i32, u8>. Shape generic muncul di seluruh standard library: Maybe<T>, Span<T>, dan sejenisnya adalah shape generic atau sum type yang dibangun dari ide yang sama.
Apakah shape disalin atau direferensikan saat dikirim ke fungsi?
Model berpikir default untuk shape adalah pass-by-value: fungsi yang dipanggil melihat salinan datanya sendiri secara logis, bukan referensi ke binding milik pemanggil. Model memori yang persis di Zero pra-1.0 masih terus berkembang (kamu akan melihat ref dan mutref di contoh standard library untuk tipe referensi yang eksplisit). Untuk sebagian besar kode aplikasi, anggap parameter shape sebagai input bertipe nilai.