3 poin oleh GN⁺ 2023-10-26 | 1 komentar | Bagikan ke WhatsApp
  • Setelah berpindah dari JavaScript ke Rust demi fokus pada WebAssembly, selama 3 tahun penulis membangun Wick, deployment produksi, ebook, dan sekitar 100 paket di crates.io, lalu menilai nilai nyata Rust
  • borrow checker, sistem tipe yang kaya, pola fungsional, dan ketiadaan null mencegah banyak bug di tahap kompilasi sehingga memungkinkan basis kode besar dengan lebih sedikit pengujian
  • Clippy dan Cargo workspace sangat kuat, tetapi celah pada tool dan ekosistem seperti konfigurasi lint global dan publish workspace berujung pada biaya operasional
  • async, refactoring, dan pengelolaan generic·lifetime·trait constraint tetap menjadi area dengan gesekan lebih besar dibanding JavaScript atau Go
  • Rust tangguh dan serbaguna, tetapi biaya perekrutan, pembelajaran, iterasi cepat, dan pelacakan masalah tinggi, sehingga lebih cocok ketika cakupan sudah jelas atau biaya awalnya bisa ditanggung

WebAssembly mendorong pemilihan Rust

  • Beberapa tahun lalu, penulis meninggalkan pekerjaan yang ada untuk fokus 100% pada WebAssembly, dan saat itu Rust memiliki dukungan kompilasi WebAssembly terbaik
  • Runtime WebAssembly yang kaya fitur juga banyak berbasis Rust, sehingga di antara pilihan yang ada, Rust menjadi opsi paling realistis
  • Setelah itu, penulis membuat Wick, framework aplikasi sekaligus runtime yang menggunakan WebAssembly sebagai sistem modul inti
  • Selama 3 tahun, pengalaman Rust terkumpul lewat berbagai deployment produksi, ebook, dan publikasi sekitar 100 paket di crates.io

Memelihara lebih banyak kode dengan lebih sedikit pengujian

  • Di Rust, penulis menulis pengujian seperti di bahasa lain pada umumnya, lalu menyadari bahwa jika kodenya bisa dikompilasi, beberapa pengujian itu praktis tidak mungkin gagal
  • Dengan menghindari blok unsafe {} dan method yang mudah memicu panic seperti .unwrap(), banyak masalah pada dasarnya bisa dihindari
  • borrow checker, sistem tipe yang kaya, pola dan library fungsional, serta tidak adanya nilai null mengurangi upaya yang dibutuhkan untuk pengujian
  • Proyek Wick dengan lebih dari 70.000 baris kode dipelihara dengan pengujian yang jauh lebih sedikit dibanding yang biasanya dibutuhkan di bahasa lain
  • Saat pengujian memang diperlukan, harness pengujian integrasi Rust memudahkan penambahan tes tepat di samping kodenya

Rust juga mengubah kebiasaan menulis kode di bahasa lain

  • Compiler Rust terus memprotes kode yang di bahasa lain dianggap normal, dan melalui proses itu kebiasaan menulis kode pun berubah
  • Kini, bahkan di bahasa lain, penulis merasa tidak nyaman jika urutan baris kode terasa janggal atau nilai kembalian tidak diperiksa
  • Saat menemui runtime error pun, penulis kini merasakan penolakan yang jauh lebih kuat dibanding sebelumnya
  • Keketatan Rust memang tidak nyaman, tetapi setelah terbiasa dengan pengalaman dilindungi compiler, sulit untuk kembali ke bahasa lain

Clippy berguna lebih dari sekadar linter

  • Clippy adalah linter untuk Rust, tetapi lebih terasa sebagai alat bantu yang ramah yang menyarankan kode pengganti, bukan sekadar alat pemeriksa
  • Standard library Rust sangat besar, dan karena fungsinya tersebar di banyak type, trait, macro, dan function, API yang dibutuhkan sering sulit ditemukan
  • Sejumlah aturan menemukan pola umum yang bisa digantikan dengan method atau type dari standard library yang lebih baik
  • Ratusan aturan mencakup performa, keterbacaan, dan indirection yang tidak perlu, serta bila memungkinkan juga menyediakan kode pengganti
  • Konfigurasi lint global tingkat proyek tampak akan dimungkinkan melalui isu Cargo, tetapi sampai saat itu Wick harus memperbarui konfigurasi lint inline di puluhan crate secara otomatis lewat skrip

Ada celah di ekosistem yang harus diterima

  • Masalah konfigurasi global Clippy adalah salah satu contoh celah ekosistem yang sering ditemui di tool dan library Rust
  • Isu terkait kini sudah ditutup, tetapi sempat terbuka selama bertahun-tahun dan penyelesaiannya memakan waktu lama
  • Rust lama dipilih sebagai “bahasa yang paling dicintai” dan berhasil menarik pengguna baru, tetapi arus itu tidak otomatis langsung menghasilkan peningkatan dramatis pada library dan tool
  • Sering muncul fork sekali pakai untuk menangani use case tertentu, dan di Wick pun saat mencoba mengirim PR, penulis mengalami situasi serupa
  • Kemungkinan alasannya mencakup tekanan untuk mempertahankan API yang stabil dan sistem tipe yang sangat terperinci
    • Pemilik library sulit menerima perubahan kecil karena itu bisa berujung pada perubahan major version
    • Menulis kode Rust yang memenuhi kebutuhan semua orang juga merupakan beban besar

Cargo, crates.io, dan gesekan saat publish workspace

  • Struktur repositori Wick dibuat dengan merujuk pada proyek-proyek populer dan awalnya terlihat masuk akal, tetapi masalah muncul pada tahap distribusi
  • Dengan Cargo, membangun, menguji, dan menggunakan crate berukuran modul itu mudah, tetapi publish ke crates.io adalah persoalan lain
  • Di crates.io, semua crate yang dirujuk harus sudah dipublikasikan secara terpisah agar sebuah paket bisa di-publish
    • Larangan mem-publish crate yang bergantung pada paket yang hanya ada di filesystem lokal memang masuk akal
    • Tetapi pada struktur alami proyek besar yang dipecah menjadi modul internal kecil, sub-crate yang hanya ada di dalam parent crate tidak bisa ikut di-publish bersama
  • Ada koreksi bahwa crate dengan local dev dependency tetap bisa di-publish tanpa menyertakan version di Cargo.toml
  • Dukungan Cargo workspace sendiri sangat bagus, dan pengalaman mengelola proyek besar lebih baik daripada kebanyakan bahasa lain
  • Namun workspace tidak menyelesaikan masalah distribusi, dan meskipun ada berbagai cara konfigurasi, sulit menemukan “jawaban benar” yang mudah dipublish
  • Banyaknya utility crate terkait cargo workspace publish justru menunjukkan adanya masalah itu sendiri
  • Saat mem-publish Wick, menggabungkan pekerjaan manual berulang dan tool yang hanya bekerja sebagian sering membuat prosesnya memakan waktu lebih dari 1 jam

async adalah salah satu sumber gesekan terbesar

  • async di Rust terasa seperti fitur yang ditambahkan setelah bahasanya selesai dibuat, dan dalam penggunaan nyata pun sering terasa seperti tempelan belakangan
  • Error-nya sulit dipahami dan diperbaiki, dan saat mencari solusi pun harus menyaring berdasarkan berbagai runtime serta pendekatan async masing-masing
  • Beberapa library async mungkin tidak dapat digunakan di luar runtime async tertentu
  • Dari sudut pandang seseorang yang telah 20 tahun memakai JavaScript dan juga punya pengalaman dengan Go, async di Rust adalah sumber frustrasi dan gesekan terbesar
  • Ini bukan masalah yang mustahil diatasi, tetapi selalu perlu bersiap bahwa masalah async bisa muncul kapan saja
  • Di bahasa lain, async hampir tidak terlihat karena bekerja dengan sangat alami

Refactoring bisa menjadi pekerjaan berat

  • Sistem tipe Rust yang kaya adalah kelebihan sekaligus kekurangan
  • Berpikir dengan tipe Rust itu baik, tetapi mengelola tipe Rust bisa menjadi mimpi buruk
  • Signature data dan function bisa memuat generic type, generic lifetime, dan trait constraint
  • Constraint itu sendiri juga bisa memiliki generic type dan lifetime lagi, sehingga terkadang type constraint justru lebih banyak daripada kode sebenarnya
  • Karena generic harus didefinisikan di setiap impl, penulisan awal pun merepotkan, dan saat refactoring perubahan kecil dapat berkembang menjadi rangkaian perubahan besar
  • Saat daftar constraint atau generic yang sama harus diulang di banyak tempat, tidak ada cara di level bahasa atau tool untuk membuat alias atau merujuk definisi terpusat, sehingga beban duplikasi tetap ada

Penilaian akhir: kuat, tetapi mahal

  • Rust sangat serbaguna hingga kode tingkat sistem, aplikasi CLI, web server, dan web client bisa ditulis dalam bahasa yang sama
  • Dengan WebAssembly, LLM yang sama dapat dijalankan di browser maupun command line dengan binary yang sama
  • Program Rust bisa sangat tangguh, dan setelah merasakan masalah-masalah yang dapat dicegah Rust, sulit untuk kembali ke bahasa lain
  • Saat sempat kembali ke Go, kecepatan pengembangan kembali terasa menarik, tetapi setelah mengalami runtime panic, keunggulan itu mulai goyah
  • Rust jelas memiliki kekurangan
    • Sulit merekrut talenta
    • Proses belajar lambat
    • Terlalu kaku untuk iterasi cepat
    • Sulit melacak masalah memori dan performa, terutama pada kode async
    • Tidak semua library cukup baik untuk kode yang aman
    • Tool pengembangan masih punya banyak ruang untuk ditingkatkan
  • Tim kecil ini berhasil melakukan hal-hal luar biasa, tetapi juga menghadapi hambatan besar, dan karena memang ada alasan teknis yang membuat Rust lebih cocok untuk Wick, penulis menilai masih terlalu dini untuk memutuskan apakah Rust benar-benar sepadan untuk Wick
  • Jika harus beriterasi cepat, Rust kemungkinan besar bukan pilihan yang tepat
  • Jika cakupan masalahnya sudah diketahui atau biaya awal yang lebih besar bisa ditanggung, Rust layak dipertimbangkan secara serius
  • Dari sudut pandang WebAssembly, kemungkinan menulis perangkat lunak tangguh sekali lalu menggunakannya kembali di banyak tempat makin terasa realistis dari bulan ke bulan

1 komentar

 
GN⁺ 2023-10-26
Opini di Hacker News
  • Saya sudah banyak memakai Rust, tetapi setelah beberapa tahun pun masih terasa kurang produktif
    Belakangan saya banyak memakai Zig; rasanya sekitar 10x lebih produktif karena saya bisa fokus pada coding yang saya inginkan saja, tanpa perlu bingung harus memakai tool atau library apa
    Saya tahu Rust memberi keamanan memori dan itu penting, tetapi kegunaannya benar-benar buruk. Setiap kali memakai Rust, rasanya seperti dibatasi, dan karena selalu harus mencari library atau menelusuri cara mengerjakan sesuatu, saya tidak bisa sekadar “mengetik kode”
    Sistem tipenya juga bisa membesar tak terkendali, dan sering kali sulit mengetahui method apa yang sebenarnya bisa dipanggil pada suatu struct. Rust adalah tool yang hebat dan menyelesaikan banyak masalah, tetapi saya tidak menganggapnya bahasa serbaguna yang baik

    • Perasaan itu tidak sama untuk semua orang. Untuk pekerjaan yang sedikit saja lebih kompleks daripada skrip shell, saya memakai Rust, dan window manager saya pun saya kendalikan dengan program Rust
      Sebagai orang yang sudah memakai Python hampir 20 tahun, sekarang saya juga bisa bekerja secepat di Python saat memakai Rust
    • Setuju. Pada titik ini, saya merasa jauh lebih produktif dengan C dan C++ daripada Rust
      Menurut saya Rust benar-benar meleset dari titik keseimbangan yang tepat. Untuk menulis aplikasi tingkat tinggi, ia terlalu rewel soal detail tingkat rendah; untuk embedded atau sistem operasi, ia terlalu kompleks
      Untuk yang pertama, saya akan memilih C++, Java, Haskell, OCaml, bahkan Go dengan sedikit campuran C; untuk yang kedua, C yang dipakai seperti macro assembler jauh lebih cocok
      Saya masih merasa gagasan awal Graydon Hoare—yakni bahasa yang lebih condong ke OCaml/SML dengan linear types, garbage collection, alokasi stack, green thread, dan CPS—akan menjadi bahasa yang jauh lebih baik
    • Pengalaman saya justru kebalikannya. Saat memakai Rust di sistem embedded, rasa percaya diri dan kecepatan saya meningkat besar
      Di C, satu kesalahan kecil sering berujung pada undefined behavior dan masalah merepotkan, tetapi di Rust hal seperti itu tidak ada, jadi benar-benar mengubah permainan
    • Saya penasaran jenis kode apa yang Anda tulis. Apakah sangat low-level, atau justru sangat high-level?
      Saya juga penasaran apakah maksudnya di Zig Anda tidak perlu mencari library atau mencari tahu cara melakukan sesuatu
    • Saya setuju dengan kesan umumnya, tetapi sulit menjelaskannya dengan kata-kata
      Rust memaksa kita memutuskan di awal ke mana setiap bit dan byte pergi, di thread mana dipakai, dan dengan cara mutasi seperti apa ditangani. Kalau bukan di level parser atau microcontroller, proses ini terasa membosankan
      Saya suka pendekatan membuat sesuatu berjalan dulu lalu menentukan struktur API terbaik, tetapi Rust bertabrakan dengan proses itu
      Meski sistem tipe Rust lebih kuat, dengan Swift pun kita bisa memperoleh 90% performanya dan alurnya terasa jauh lebih alami
  • Tidak adanya namespace di crates.io mungkin adalah kritik terbesar
    Siapa pun bisa mengambil lebih dulu nama paket umum di ruang global, dan kecuali menghindari repositori crates.io, kebanyakan orang harus menerimanya. Padahal sebagian paket dengan nama umum yang sudah diambil seperti itu bukanlah paket terbaik untuk dipakai
    Mungkin ini reaksi balik terhadap notasi reverse DNS ala Java yang panjang dan menyebalkan, tetapi pendekatan seperti GitHub—menambahkan namespace pengguna/grup di depan nama paket—sepertinya akan menjadi jalan tengah yang baik

    • Saya pernah membuat analisis untuk mencari penyerobot nama di crates.io, dan hitungannya menunjukkan penyerobot teratas membuat crate dengan laju sekitar satu crate tiap 30 detik selama seminggu penuh
      Saya mengirim analisis itu ke tim crates.io dan juga menunjukkan adanya kebijakan yang melarang otomasi, tetapi mereka menjawab bahwa itu belum menjadi bukti yang cukup bahwa ada penyerobotan nama
      Masalah crates.io adalah meski punya kebijakan yang jelas, kebijakan itu tidak ditegakkan. Jadi nama crate yang pendek dan mudah diingat sudah habis diambil, dan tidak ada cara untuk mendapatkannya kembali
    • Ini tampaknya bukan reaksi balik terhadap reverse DNS ala Java, melainkan lebih seperti mengikuti konvensi yang ditetapkan kebanyakan package manager saat itu
      NPM, PyPI, RubyGems, Hex dari Elixir, Cabal dari Haskell, dan lainnya—sekitar 2014–2015 saat Rust muncul, saya sulit mengingat package manager non-Java yang bukan memakai satu namespace global
      Sebagian kemudian mencoba memperbaikinya, tetapi saat itu memang era ketika package manager bekerja seperti itu
    • Maven dan Java kurang mendapat apresiasi dalam hal manajemen dependensi yang bekerja dengan baik
      Sistem manajemen dependensi yang lebih buruk dari bahasa-bahasa lain setelahnya hampir tidak belajar dari contoh sebelumnya
    • Pendekatan memakai URL untuk paket cukup masuk akal. Ini bekerja dengan baik di ekosistem Go
      Keuntungannya, bahasa tidak lagi membutuhkan database paket global. Jika Anda menaruh paket di example.com/your-thing, itu praktis langsung menjadi rilis
      Tentu saja, cache dan mesin pencari bisa disediakan terpisah jika diinginkan
    • Saya tidak sering memakai Rust, tetapi masalah seperti ini benar-benar menyebalkan di repositori paket secara umum
      Contohnya, http-server buruk jadi jangan dipakai, pakailah MuffinTop; hal semacam itu harus diketahui begitu saja
      Konsep nama paket yang tersertifikasi menarik, tetapi jika seiring waktu kode di balik alias berubah, dalam praktiknya kemungkinan akan membingungkan
      Pada akhirnya, sepertinya ini akan tetap menjadi bagian dari proses menjadi pakar domain di ekosistem mana pun
  • Jika membuat .cargo/config.toml di root workspace, itu berlaku untuk semua crate, sehingga bisa mengatur lint Clippy global
    Di dalam file, cukup masukkan sesuatu seperti rustflags = ["-Wclippy::lint_name_to_warn", "-Dclippy::lint_name_to_deny"] di bawah [build]
    Namun, rustflags bersifat menimpa, bukan menambahkan, jadi jika ada sumber lain seperti variabel lingkungan RUSTFLAGS, sumber itu akan menimpa pengaturan ini

    • Kami menjalankan skrip saat commit untuk menambahkan lint ke file lib.rs atau main.rs. Sederhana
  • Saya belajar Rust karena tampaknya jelas akan menjadi penting secara profesional. Saya benar-benar ingin menyukainya dan bisa melihat kelebihannya, tetapi sejauh ini Rust termasuk salah satu bahasa paling tidak menyenangkan yang pernah saya pakai
    Saya terus berharap rasa tidak suka itu akan hilang seiring meningkatnya kemahiran, tetapi makin saya menaiki kurva belajarnya, tetap saja tidak terasa makin sayang
    Tidak apa-apa. Ini mungkin bukan satu-satunya bahasa yang saya benci meski bisa memakainya dengan mahir. Hanya saja, begitu banyak orang bilang mereka mencintai Rust sehingga saya kira saya juga akan menikmatinya

    • Sebagai kontra-contoh, saya suka pemrograman Rust. Masa-masa bertarung dengan borrow checker sudah lama berlalu, dan belakangan error pun jarang, kecuali saat saya sengaja memicunya untuk memeriksa tipe
      Kompiler Rust juga tampaknya makin baik dalam menerima lebih banyak kasus yang valid
      Kunci memahami borrow checker adalah memahami model memori yang mendasarinya. Model memori Rust sama dengan C, kecuali perluasan untuk abstraksi seperti generic
      Aturan borrow checker awalnya tampak sewenang-wenang, tetapi sangat terkait dengan model memori ini. Saat tanpa sengaja tersandung borrow checker, justru di situlah nilainya, karena itu berarti bug yang dibuat akibat kurang fokus
      Yang menakutkan adalah bahasa seperti C atau C++ bisa saja menerima kode semacam itu begitu saja dan lanjut
      Sistem tipe Rust yang ketat dan borrow checker-nya mendorong dengan halus agar kode distrukturkan dengan benar, dan saya yakin itu memperbaiki desain kode saya di semua bahasa yang saya pakai
    • Saya sudah beberapa kali mencoba mempelajari Rust, tetapi terus terpental. Rasanya memang usability-nya kurang baik
    • Yang masih mengganjal bagi saya adalah tidak adanya argumen fungsi default/bernama
      Itu fitur usability programmer yang sangat mendasar dan dimiliki sebagian besar bahasa populer, bahkan C++ sudah lama punya argumen default
    • Saya penasaran apa yang tidak disukai
  • Saya mantan programmer C/C++ yang selama 10 tahun hampir tiap minggu memanggil pthread, dan sekarang saya memakai Rust async di mana-mana
    Saya tidak tahu kenapa async begitu dibenci. Menurut saya semua orang seharusnya memakai async untuk semua hal. Termasuk pekerjaan “sederhana” yang dari luar terlihat single-threaded

    • Menurut saya masalahnya adalah sifatnya yang menular. Terutama di lingkungan embedded atau Wasm, async arus utama belum tentu async yang saya inginkan
      Kalau use case penulisnya Wasm, pasti perspektifnya akan berbeda
      Pekerjaan yang memakai buffer besar atau menggunakannya kembali untuk menghindari biaya alokasi sering kali juga diuntungkan oleh thread pool gaya lama. Bump allocator atau sharded allocator bisa menyelesaikan sebagian, tetapi untuk loop ketat yang bisa divektorisasi dan CPU-bound, thread pool bekerja lebih baik
      Async adalah alat yang bagus, tetapi bukan berarti selalu konteks yang optimal
    • Baru-baru ini saya sedikit memakai Rust async untuk membandingkan bagaimana penanganan error pada panggilan async bertingkat berbeda dari Go, tetapi bahkan contoh sepele yang ingin saya tulis tampaknya tidak bisa dilakukan tanpa Tokio
      Go, C#, TypeScript tidak punya hambatan seperti itu
      Misalnya, tanpa decorator yang diimpor dari Tokio, sepertinya kita bahkan tidak bisa memakai await di dalam fungsi main
    • Masalah yang saya hadapi sekarang adalah beberapa item seperti rhai Engine bukan Send, tetapi saya mencoba memakainya di dalam closure async
      GPT-4 menyarankan membuat tokio Runtime di dalam thread dan memakai block_on(). Saya akan mencobanya besok. Ini proyek Rust serius pertama saya
    • Saya justru belajar sebaliknya. Programmer cenderung membuat semuanya async secara tidak perlu, padahal tidak dibutuhkan, sehingga menambah kompleksitas dan beban mental
    • Bisa jelaskan lebih rinci? Saya penasaran contoh pekerjaan sederhana yang tampak single-threaded tetapi layak memilih async itu seperti apa
      Saya juga penasaran apakah “sekarang memakai Rust async di mana-mana” berarti “memakai Tokio di mana-mana”
  • Pemrograman Rust benar-benar berbeda dari hubungan yang abusif. Kompiler berusaha membantu semaksimal mungkin, dan khususnya pesan error rustc termasuk yang terbaik di dunia

    • Sistem operasi ingin programmer menangani resource dengan benar, dan kompiler Rust membuat hal itu sangat mudah
      Yang lebih mirip hubungan abusif bukan kompiler Rust, melainkan sistem operasinya. Hardware juga sama, karena assembly harus dijalankan dengan benar; kalau dilihat begitu, itu juga bisa disebut hubungan abusif
      Pesan error Rust tak tertandingi, tidak ada kompiler lain yang mendekati
      Sebagai tambahan, saya baru-baru ini memakai LaTeX dan pesan error-nya mengerikan. Proses menatap error untuk memahami apa yang salah benar-benar seperti mimpi buruk
    • Secara umum bagus, tetapi saya sangat tidak suka ketika error apa pun di dalam fungsi async menghasilkan error bahwa Future tidak lagi Send dan Sync di semua titik pemanggilan rekursif
      Seluruh konsol tertutup error, dan error sintaks sebenarnya terkubur di suatu tempat di tengahnya
    • Kompiler Rust adalah kompiler pertama yang pernah saya lihat memakai kata “perhaps”
      Keluhan utama saya adalah masih belum sepenuhnya memahami lifetime, dan kompiler juga tidak selalu bisa membantu. Saya mengerti alasannya, karena kompiler mengambil keputusan secara konservatif
  • Dalam pengujian C++, orang sering berkata “kalau sudah bisa dikompilasi, umumnya sudah benar”
    Jika Anda berpikir Rust menangani begitu banyak kesalahan sehingga kasus pengujian yang umum menjadi tidak bermakna, itu menurut saya tanda bahwa di bahasa lain Anda tidak menguji hal yang benar
    Yang perlu diuji bukanlah masalah bahasa itu sendiri, melainkan logika bisnis
    Jika saat melihat kode pengujian Anda merasa “kalau JavaScript, ini akan saya uji, tapi di Rust tidak perlu”, maka pengujian itu cukup dihapus saja

    • Saya pernah mendengar ungkapan “kalau sudah bisa dikompilasi, umumnya sudah benar” untuk Haskell dan Rust, tapi belum pernah mendengarnya diterapkan pada C++
    • Exception null pointer adalah bug yang merusak logika bisnis
      Tidak ada pemisahan “logika bisnis vs masalah bahasa”. Karena bahasa adalah fondasi tempat logika bisnis berada
      Jika tidak menguji mode kegagalan, saya tidak tahu apa makna pengujian itu
    • Ada semacam kehebatan aneh pada tipe programmer C++ yang menganggap kode sampah rusak mungkin benar karena berhasil dikompilasi
      Berbeda dari kebanyakan bahasa yang familier, C++ memiliki IFNDR, yang secara bercanda disebut false positive untuk pertanyaan “apakah ini program C++?”
      Compiler C++ yang mengikuti standar dilarang memberi tahu dalam sebagian kasus ketika kode yang ditulis dicurigai tidak masuk akal, dan harus terus berjalan begitu saja lalu menghasilkan sesuatu
      Itu bisa saja executable yang berjalan, atau executable yang menimbulkan bencana setiap hari Jumat. Tidak ada cara untuk mengetahuinya
      Standar ISO memang mengidentifikasi kasus seperti ini, tetapi terlalu kabur sehingga sulit menangkap dengan tepat apa saja yang termasuk, dan dugaan saya sebagian besar software C++ non-trivial saat ini sebenarnya IFNDR. Lebih baik menolak seluruh bahasa itu saja
  • Rust tampaknya akhirnya meruntuhkan gagasan bahwa programmer harus sepenuhnya mengendalikan dan menyadari semua hal yang dilakukan compiler
    Sebenarnya sejak puluhan tahun lalu pun sudah tidak demikian, dan compiler nyaris seperti sihir. Rust, lewat borrowing, banyak membalik arus itu, membuat orang lebih nyaman dengan kenyataan bahwa compiler lebih tahu daripada mereka
    Saya berharap orang bisa menjadi lebih nyaman lagi. Kecuali memang diperlukan secara algoritmis, kita tidak semestinya harus secara eksplisit mengiterasi collection dari depan. Banyak operasi semestinya diparalelkan secara implisit. Saya ingin ada Bash yang bergaya Rust

    • Ini sepenuhnya berlawanan dengan pengalaman saya memakai Rust
      Rust cukup transparan tentang apa yang dilakukannya, dan sangat konservatif terhadap sihir compiler. Bahasanya tidak melakukan alokasi heap, tidak melakukan reference counting, dan tidak ada konversi tipe numerik implisit
      Tipe yang tidak dinyatakan dapat disalin secara implisit tidak akan disalin, dan bahkan itu pun hanya legal pada tipe yang bisa disalin dengan memcpy dangkal sederhana
      Rust memakai abstraksi tanpa biaya di banyak tempat, sehingga kita bisa memprediksi akan dikompilasi menjadi kode seperti apa, dan biasanya sederhana. Layout dasar tipe standar juga diketahui dengan baik, sehingga kita tahu iterasi Vec akan dikompilasi menjadi loop yang menaikkan pointer, dan tidak ada paralelisme implisit
      Menggambarkan borrowing sebagai “compiler lebih tahu daripada programmer” itu aneh. Borrowing mirip dengan pemeriksaan tipe. Jika Anda mendeklarasikan suatu tipe sebagai sementara lalu mencoba memakainya seolah-olah berumur panjang, akan muncul error
      Sama seperti fungsi yang dideklarasikan mengembalikan struct Foo tetapi mengembalikan Bar akan menghasilkan error. Alasan compiler “lebih tahu” hanyalah karena Anda menulis bug
      Borrowing juga dikompilasi menjadi penggunaan pointer langsung tanpa garbage collection, dan pada struct serta fungsi C ABI secara harfiah dijamin sama dengan pointer C. Jika Anda merasa lebih tahu daripada compiler, Anda juga bisa melewati lifetime dengan unsafe
    • Sudah ada crate yang menyediakan iterator paralel. Cukup ubah nama pemanggilan iter()
      Namun saya tidak setuju bahwa itu harus implisit
    • Ungkapan “tidak bisa mengendalikan apa yang dilakukan compiler” agak berlebihan
      Dalam beberapa hal, Rust memberi programmer lebih banyak kendali daripada C. Misalnya Rust mendukung inline assembly sebagai standar, sedangkan inline assembly di C bergantung pada ekstensi masing-masing vendor
      Namun default yang nyaman memang sangat berbeda. Di Rust, type casting yang tidak aman menuntut banyak prosedur dan kehati-hatian, serta harus mengikuti lebih banyak aturan daripada C
      Khususnya, reference di Rust pada dasarnya semuanya berperilaku seperti restrict, dan ini sangat mudah dirusak ketika melakukan casting unsafe dari raw pointer ke reference yang aman. Karena itu, jika ada pilihan, muncul insentif kuat untuk tidak menulis kode semacam itu
    • Sebagai orang yang banyak memakai unsafe Rust, termasuk hal-hal seperti tagged pointer, saya sangat tidak setuju
      Justru saya menginginkan kendali yang lebih eksplisit, dan ingin mengurangi bebannya dengan sistem tipe yang lebih ekspresif. Idealnya, sistem tipe Rust menjadi seperti varian Prolog
    • “Bash bergaya Rust” berarti Bash yang memiliki tipe, terutama floating point, memiliki lebih sedikit kondisi pengecualian, serta fungsi dengan parameter eksplisit dan flag command-line yang sederhana
  • Belajar kapan harus berinvestasi pada batasan tipe dan kapan tidak adalah pelajaran penting
    Ini bukan masalah khusus Rust, tetapi cara mengekspresikannya bisa sedikit berbeda
    Saya pernah menangani C++ yang terlalu banyak tipe dan Java yang terlalu diabstraksikan serta terlalu banyak tipe, dan keduanya punya masalah refactoring yang sejenis
    Sebaliknya, saya juga sering melihat Go yang kekurangan tipe dan dokumentasi, sehingga nilai-nilai tertentu tersebar ke mana-mana menjadi ranjau runtime, dan refactoring bisa menjadi sangat sulit
    Rasa kemajuan di awal memang lebih cepat, tetapi biasanya Anda akhirnya mengirim bug kepada pengguna
    Tidak ada jawaban ajaib untuk trade-off ini. Rust memberi pilihan yang cukup luas pada sumbu ini

  • Pernyataan bahwa “Rust berteriak sepanjang hari, setiap hari, tentang hal-hal yang dalam kehidupan lama dulu dianggap sepenuhnya normal” juga kurang lebih dilakukan oleh compiler C yang bagus jika semua flag diaktifkan
    Saya suka bahasa dan compiler yang memungkinkan kita mematikan teriakan itu secara selektif dan sengaja menulis kode buruk. Kode buruk yang berjalan dan bisa ditulis cepat sering kali lebih baik daripada kode yang sempurna tetapi memakan waktu selamanya
    Kita bisa membuat proof of concept yang buruk tetapi berjalan, lalu memperbaikinya agar tidak terlalu buruk
    Poin bahwa “pengguna baru memang berhasil ditarik masuk, tetapi library atau tool tidak membaik secara dramatis, dan yang muncul hanya fork sekali pakai untuk menangani use case tertentu” tidak ada hubungannya dengan usia
    Menarik core developer itu sulit, dan perlu banyak usaha agar hal itu menarik. Selain itu, konvensi budaya ditentukan oleh para adopter awal, dan tidak adanya konvensi sering kali sama merugikannya dengan konvensi yang buruk
    Kalau melihat Python, akibat pendekatan yang longgar terhadap lingkungan pengembangan dan eksekusi, kini ada sekitar 50 cara yang saling bersaing untuk mengembangkan atau menjalankan program Python
    Repositori paket yang paling banyak dipakai, PyPI, selama bertahun-tahun berantakan; sedikit orang yang membangun di atas paket yang sudah ada; namanya tampak seperti generator kata acak; ekosistemnya penuh malware; bahkan mencari paket dari command line pun tidak bisa
    Ini bukan salah bahasanya, melainkan salah komunitas dan core team yang bersikap seperti penonton. Budaya lebih penting daripada teknologi yang ada di pusatnya
    Saya tidak bermaksud hanya mengkritik Python; saya menyebutnya karena lebih memahami masalahnya. C sudah ada selama setengah abad, tetapi komunitasnya pun belum benar-benar merapikan bahkan setengah dari solusi yang sudah disediakan bahasa-bahasa yang lebih modern

    • Rust juga mendukung itu. Cukup tandai semuanya sebagai unsafe
    • Tidak mungkin Linux dan Windows mulai mem-porting komponen ke Rust karena “tidak ada library yang lebih baik”
    • Kalau boleh bicara blak-blakan, itu sangat mirip dengan TypeScript
      Maksudnya situasi ketika compiler berteriak menyuruh kita memperbaiki sesuatu, tetapi kita hanya ingin menguji sebuah ide sebelum memolesnya sampai sempurna