Enum dan struct adalah dua tipe yang melayani kebutuhan berbeda dalam pemodelan data. Enum membatasi nilai pada himpunan konstanta bernama, sedangkan struct menempatkan nilai kecil langsung pada memori alih-alih sebagai referensi. Topik ini membahas deklarasi keduanya, perbandingan enum dengan discriminated union, serta kondisi yang membuat struct memberi keuntungan nyata.
Enum: himpunan konstanta bernomor#
Enum adalah tipe yang seluruh nilainya berupa konstanta bernama dengan bilangan bulat tetap di baliknya. Deklarasinya menggunakan kata kunci type diikuti daftar Nama = angka yang dipisahkan |. Nilai diakses melalui nama tipe, misalnya HariPiket.Selasa, sehingga maksudnya terbaca tanpa perlu mengingat angkanya.
Berkas berikut mendefinisikan enum hari piket kelas, membaca nomor urut sebuah nilai, lalu membangun nilai berikutnya dari nomor urut tersebut.
// Himpunan konstanta hari piket kelas.
type HariPiket =
| Senin = 0
| Selasa = 1
| Rabu = 2
let hariIni = HariPiket.Selasa
printfn "%A" hariIni
printfn "nomor urut: %d" (int hariIni)
let hariBerikut = enum<HariPiket> ((int hariIni + 1) % 3)
printfn "%A" hariBerikutSelasa
nomor urut: 1
RabuFungsi int mengambil bilangan di balik nilai enum, sedangkan fungsi enum<HariPiket> membangun nilai enum dari bilangan. Kombinasi keduanya dengan sisa bagi membentuk siklus tiga hari tanpa percabangan. Keluaran %A menampilkan nama konstanta, bukan angkanya, sehingga nilai tetap terbaca sebagai nama.
Enum menutup himpunan nilai yang sah pada satu deklarasi. Bilangan ajaib seperti 1 tidak perlu tersebar di kode karena setiap angka sudah diberi nama, dan perbandingan dua nilai enum mengikuti angka di baliknya, sehingga HariPiket.Rabu > HariPiket.Senin bernilai true. Angka di balik konstanta juga berguna ketika data enum disimpan ke berkas atau dikirim antar program, karena yang dikirim hanyalah bilangannya.
Enum dibandingkan discriminated union#
Enum dan DU sama-sama membatasi nilai pada sejumlah kasus bernama, tetapi keduanya berbeda pada isi kasusnya. Enum membawa satu bilangan bulat dan tidak dapat menampung data tambahan, sedangkan DU membawa data yang bentuknya bebas per kasus.
| Aspek | Enum | Discriminated union |
|---|---|---|
| Isi setiap kasus | nomor urut saja | data dengan bentuk bebas per kasus |
| Representasi | bilangan bulat tetap | kasus beserta datanya |
| Konsumsi | konversi ke int atau pembandingan nama | pattern matching yang membongkar data |
| Lintas bahasa | tipe .NET yang terbaca langsung dari C# | tipe khas F# |
Aturan praktisnya mengikuti isi data. Himpunan konstanta tanpa data tambahan, seperti hari, tingkat kesulitan, atau arah mata angin, cukup ditulis sebagai enum. Kasus yang membawa data, seperti Dipinjam dengan nama peminjamnya, membutuhkan DU. Tipe enum juga dapat digunakan sebagai tipe pada field record, sehingga keduanya dapat dipadukan pada satu model.
Struct: tipe nilai tanpa alokasi pada heap#
Struct adalah tipe nilai (value type), yaitu tipe yang nilainya disimpan langsung di tempatnya berada, bukan sebagai referensi yang menunjuk objek pada heap. Atribut [<Struct>] mengubah deklarasi record biasa menjadi struct tanpa mengubah cara penulisannya di tempat lain.
// Titik dua dimensi sebagai struct (value type).
[<Struct>]
type Titik =
{ X: float
Y: float }
let a = { X = 3.0; Y = 4.0 }
let b = a
printfn "%A" a
printfn "tipe nilai: %b" (typeof<Titik>.IsValueType)
printfn "kesetaraan struktural: %b" (a = b){ X = 3.0
Y = 4.0 }
tipe nilai: true
kesetaraan struktural: trueKeluaran di atas menegaskan tiga hal. Pemeriksaan IsValueType bernilai true, sehingga Titik benar-benar tipe nilai. Kesetaraan struktural juga tetap berlaku dan membandingkan isi field, sama seperti record biasa. Pemberian let b = a pada struct menyalin nilainya, sedangkan pada record biasa yang disalin hanyalah referensinya.
Struct pada contoh dibangun dengan pembuat record biasa, sehingga atribut [<Struct>] hanya terlihat pada pemeriksaan tipenya. Fungsi typeof<Titik>.IsValueType membaca metadata tipe, sehingga sifat tipe nilai dapat diuji langsung dari kode tanpa alat tambahan.
Perbedaan penyimpanan itu berdampak pada alokasi. Record biasa membuat satu objek baru pada heap untuk setiap nilainya, sedangkan nilai struct tinggal di tempatnya berada, misalnya pada variabel lokal atau di dalam array. Bentuk penulisannya tidak berubah sama sekali, sehingga perpindahan dari record biasa ke struct tidak menuntut penulisan ulang kode yang menggunakannya.
Atribut [<Struct>] juga berlaku pada DU yang setiap kasusnya membawa paling banyak satu nilai.
[<Struct>]
type Suhu =
| Celsius of float
| Fahrenheit of float
let pagi = Celsius 24.0
printfn "%A" pagi
printfn "%b" (typeof<Suhu>.IsValueType)Celsius 24.0
trueKapan struct memberi keuntungan#
Struct memberi keuntungan pada data kecil yang jumlahnya banyak dan berumur pendek. Setiap nilai tidak membutuhkan satu objek tersendiri pada heap, sehingga tekanan terhadap pengumpul sampah (garbage collector) berkurang. Array berisi ribuan elemen struct tersimpan sebagai rangkaian nilai yang berurutan, bukan rangkaian referensi yang tersebar, dan pola semacam ini lazim pada geometri, grafik, dan perhitungan numerik.
Manfaat itu tidak berlaku searah. Struct disalin setiap kali diberikan ke variabel baru atau dikirim ke fungsi, sehingga struct berukuran besar justru menambah beban penyalinan. Struct yang paling menguntungkan memiliki beberapa field numerik, seperti titik, vektor, atau pasangan koordinat.
Perbandingan dengan struct yang besar memperjelas batasnya. Struct dengan sepuluh field akan disalin lengkap pada setiap pemberian nilai, sedangkan record besar hanya memindahkan referensinya. Dengan demikian, keuntungan alokasi perlu ditimbang ulang terhadap biaya penyalinan ketika struct tumbuh melebihi beberapa field numerik.
Ringkasan#
- Enum membatasi nilai pada konstanta bernama berbilangan bulat, dengan konversi dua arah lewat
intdanenum<T>. - Enum tidak menampung data per kasus, sedangkan DU membawa data bebas per kasus, sehingga keduanya melayani kebutuhan yang berbeda.
- Atribut
[<Struct>]menjadikan record atau DU sebagai tipe nilai yang tersimpan langsung tanpa objek pada heap. - Struct memberi keuntungan pada nilai kecil yang banyak dan berumur pendek, sedangkan struct besar justru membebani proses penyalinan.
Referensi#
- Enumerations — Microsoft Learn — Dokumentasi resmi enum F#, termasuk konversi dan nilai di balik konstanta.
- Structures — Microsoft Learn — Dokumentasi resmi struct F#, termasuk atribut Struct pada record dan discriminated union.