Perbandingan Ada dan Rust melalui penyelesaian masalah AoC
(github.com/johnperry-math)- Membandingkan perbedaan dan karakteristik yang muncul saat menyelesaikan masalah Advent of Code dengan dua bahasa, Ada dan Rust
- Menganalisis perbedaan desain bahasa dan cara penulisan program nyata pada kedua bahasa yang berfokus pada keamanan dan keandalan
- Perbedaan tampak dari berbagai sudut pandang seperti library standar, apakah fitur tersedia secara bawaan, perbedaan performa, serta gaya penanganan error
- Menjelaskan contoh konkret yang ditemui saat benar-benar menulis dan mengoperasikan kode, seperti modularitas, generic, loop, dan penanganan error melalui contoh kode praktis
- Perbedaan pengalaman pengembangan terlihat jelas dari perbedaan pada cara pengetikan statis, pemrosesan array, dan antarmuka penanganan error
Pengenalan dan tujuan
- Saat menyelesaikan masalah Advent of Code (selanjutnya disebut AoC), penulis awalnya hanya menggunakan Ada, lalu sejak 2023 juga menulis solusi dengan Rust dan Modula-2 sehingga bisa membandingkannya secara langsung
- Ketika memindahkan solusi yang sebelumnya berpusat pada Ada ke Rust, penulis merasakan perbedaan struktural dan pendekatan khas dari kedua bahasa tersebut
- Tujuannya adalah memperjelas perbedaan penggunaan nyata dari sudut pandang keamanan kode, keandalan, dan desain bahasa
Versi bahasa yang digunakan untuk perbandingan
- Ada 2022 (sebagian aturan Spark 2014 dirujuk bila diperlukan)
- Rust 2021 (untuk perbandingan utama berbasis Rust 1.81.0)
Fitur yang dikecualikan dan kriteria perbandingan
- Fitur representatif dari masing-masing bahasa (= fitur andalan) disebutkan secara singkat sebagai komentar di dalam pembahasan
- Ada pula beberapa fitur yang tidak dibahas, bergantung pada pengalaman pribadi dan kebutuhan nyata dari masing-masing solusi
- Sebisa mungkin menghindari opini pribadi dan berfokus pada karakteristik utama
Latar belakang dan sudut pandang penulis
- Sebagai pengguna nonpenutur asli untuk Ada maupun Rust, dasar pengalaman penulis berasal dari bahasa era 1980-an seperti C/C++, Pascal, dan Modula-2
- Akibatnya, gaya kode yang digunakan bisa berbeda dari gaya modern atau idiomatik
- Implementasinya mungkin bukan yang paling optimal, dan tergantung situasi masalah, terkadang dipilih solusi yang intuitif atau tidak lazim
Posisi Ada dan Rust
- Hingga kini Ada tetap menjadi bahasa untuk pengembangan sistem/embedded yang sangat aman dan andal, dengan penekanan pada keterbacaan kode
- Rust memiliki kekuatan pada keamanan memori dan system programming, serta selama bertahun-tahun terpilih sebagai ‘bahasa yang paling disukai’ dalam survei pengembang Stack Overflow
- Ada adalah bahasa tingkat tinggi serbaguna yang menawarkan spektrum yang kuat untuk pembacaan dan pemeliharaan kode
- Rust berorientasi pada pengembangan program sistem tingkat rendah, dengan budaya pemrograman aman berbasis manajemen memori eksplisit serta tipe error/option
Perbandingan keamanan dan karakteristik struktural
-
Ada
- Standar ISO (spesifikasi ketat)
- Mudah mendeklarasikan tipe yang sesuai dengan karakteristik masalah (rentang, jumlah digit, dan sebagainya)
- Indeks array boleh tidak berupa angka
- Ada spesifikasi yang lebih ketat bernama Spark
-
Rust
- Spesifikasi berpusat pada dokumentasi resmi (Reference) dan compiler
- Deklarasi tipe bergantung pada tipe mesin (misalnya
f64,u32) - Pengindeksan array secara alami hanya cocok untuk tipe numerik
Ringkasan utama tabel fitur/ketersediaan bawaan
- Ada perbedaan pada dukungan seperti pengecekan rentang array, container generic, konkurensi, loop berlabel, dan pattern matching
- Ada menggunakan penanganan error berbasis Exception (pengecualian), sedangkan Rust menggunakan pendekatan berbasis nilai balik melalui tipe Result/Option
- Rust menonjol dalam dukungan macro, pattern matching, dan kemurnian fungsional
- Ada mendukung desain berbasis kontrak serta verifikasi compile-time DBC (Design By Contract) melalui Spark
- Dari sisi keamanan memori, Rust dan Spark menerapkannya secara paksa, sementara Ada tetap memperbolehkan penggunaan pointer Null
Perbandingan performa dan waktu eksekusi
- Secara umum Rust dikenal cepat saat runtime tetapi lambat saat kompilasi, sedangkan Ada sebaliknya dikenal cepat saat kompilasi dan agak lebih lambat saat runtime tergantung pengecekan verifikasi
- Hasil benchmark menunjukkan bahwa pada masalah day24, Rust mengalami overflow karena keterbatasan tipe f64, sedangkan Ada memungkinkan penentuan tipe tingkat tinggi seperti digits 18, sehingga dapat memilih tipe mesin secara otomatis, menghindari overflow, dan menunjukkan performa unggul
- Rust perlu menggunakan f128 yang belum stabil atau library eksternal, sedangkan Ada dapat unggul hanya dengan penentuan tipe yang sesuai dengan spesifikasi compiler
Pemrosesan file dan penanganan error (Studi Kasus 1)
Pemrosesan file di Ada
- Secara default menggunakan Ada.Text_IO
- Membuka file secara eksplisit, membaca per baris, serta menangani Line berdasarkan rentang atau posisi yang diinginkan secara relatif intuitif
- Saat terjadi error, penanganannya berupa exception alih-alih pesan error yang jelas, dan kemungkinan terjadinya error tidak tampak pada signature fungsi
Pemrosesan file di Rust
- Menggunakan std::fs::File dan BufReader
- Saat membuka file, hasil dikembalikan sebagai tipe Result, sehingga kemungkinan error terlihat jelas
- Tidak mendukung akses indeks karakter secara langsung, dan harus diproses melalui Iterator
- Berpusat pada alat fungsional dan iteratif seperti map, filter, collect, sum, serta mendukung berbagai macro (misalnya
include_str!) - Error dinyatakan secara eksplisit pada tipe nilai balik, sehingga kejelasan propagasi error di tingkat fungsi dapat dijaga
Modularitas dan generic (Studi Kasus 2)
Modularitas di Ada
- Pemisahan yang jelas antara spesifikasi (antarmuka) dan implementasi berbasis package
- Untuk memperkuat modularisasi, digunakan subpackage dan kombinasi sintaks use/rename guna menyesuaikan keterbacaan
- Dukungan generic pada package: dapat menggeneralisasi tipe/konstanta/seluruh subpackage
Modularitas di Rust
- Modul disusun dengan sistem mod/crate, dan pemisahan spesifikasi serta implementasi diotomatisasi oleh pembuat dokumentasi
- Penentuan akses pub/private memberikan kontrol akses yang deklaratif
- Menggunakan use/as untuk kombinasi impor/pergantian nama
- Dukungan pengujian bawaan memungkinkan deklarasi modul tes langsung di dalam kode, lalu dibangun dan dijalankan otomatis
Generic
- Ada hanya mendukung generic pada tingkat package/procedure (tidak mendukung tipe tunggal secara langsung)
- Rust dapat menerapkan generic langsung pada tipe (berbasis template)
- Ada dapat mengekspresikan karakteristik tambahan seperti rentang tipe secara jelas melalui range type dan subtype, sedangkan Rust memanfaatkan konstanta instans
Perbandingan tipe enumerasi (Studi Kasus 3)
- Ada mendukung deklarasi ringkas sekaligus secara otomatis mendukung penggunaan diskret, berurutan, loop iteratif, dan indeks
- Deklarasi enum Rust juga mirip, tetapi pendekatan seperti pattern matching dan iterasi memerlukan cara yang lebih eksplisit
Kesimpulan
- Dalam hal tipe spesifikasi tingkat tinggi, kemampuan verifikasi, dan pengecekan saat eksekusi, Ada memberikan kontrol yang lebih ketat
- Dalam hal gaya pemrograman fungsional, pemrograman macro, dan penanganan error dengan bantuan compiler, Rust unggul dalam kemudahan pengembangan sekaligus keamanan
- Dalam penyelesaian masalah nyata, Ada memiliki kekuatan pada kompatibilitas dengan kode lama dan pemeliharaan, sedangkan Rust unggul pada ekosistem alat pengembangan modern serta dukungan keamanan/paralelisme
1 komentar
Komentar Hacker News
Tautan penjelasan Nim Subranges
Dokumen terkait
Spesifikasi Rust
charsebagai “string”, sehingga mudah diindeks seperti array byte biasa. Rust sejak awal dirancang dengan kesadaran terhadap Unicode, jadi string di Rust pada dasarnya adalah teks sungguhan yang dikodekan dalam UTF-8. Karena itu, Ada memungkinkan random indexing seperti array, sedangkan di Rust konsep string-nya berbeda sehingga ada pilihan untuk mengubahnya menjadi array byte biasastr::as_bytesSitus Prunt
Prunt GitHub
Komentar HN terkait
pub const SIDE_LENGTH: usize = ROW_LENGTH;