Elixir v1.20: Kini Menjadi Bahasa dengan Tipe Bertahap
(elixir-lang.org)- Inferensi tipe dan pemeriksaan tipe bertahap (gradual) diterapkan pada semua program Elixir, sehingga dapat menemukan kode mati dan bug yang terverifikasi yang pasti gagal saat runtime tanpa anotasi tipe
- Tipe
dynamic()berbeda dariany()yang “mengizinkan apa pun”; ia melacak rentang tipe yang mungkin saat runtime dan hanya melaporkan pelanggaran ketika tidak sepenuhnya tumpang tindih dengan tipe yang diizinkan - Nilai
dynamic(integer() or binary())tidak memunculkan pelanggaran pada pemanggilan yang sebagian kemungkinan tipenya masih tumpang tindih, seperti operasi numerik atau fungsi string, tetapi akan memunculkan pelanggaran pada pemanggilan yang hanya menerima map sepertiMap.fetch! dynamic()dipersempit berdasarkan cara penggunaannya, dan pada kode sepertidata.a + data.b,datadisempurnakan menjadi map berbentuk%{..., a: number(), b: number()}- Dalam guard, union, intersection, dan negation diinferensikan sehingga kondisi seperti
is_list,is_integer,is_map_key,not is_map_key, dantuple_sizedapat dimanfaatkan sebagai informasi tipe casedan ekspresi kondisional mencerminkan informasi dari klausa sebelumnya ke klausa berikutnya, sehingga pemeriksaan tipe dapat dilakukan dengan cara seperti menanganinillebih dulu lalu mempersempit nilai yang tersisa menjadibinary()- Berbagai fungsi terkait tuple dan map di pustaka standar kini ditambahkan tipe, membantu menemukan klausa duplikat dan kode mati pada codebase yang sudah ada
- Pada “If T: Benchmark for Type Narrowing”, Elixir lulus 12 dari 13 kategori, menunjukkan bahwa informasi tipe yang presisi dapat dipulihkan dari kode Elixir umum
- v1.20 juga kembali meningkatkan waktu kompilasi untuk aplikasi di lingkungan multi-core, dan dalam benchmark sintetis, build tool Elixir menunjukkan hasil tercepat di antara bahasa-bahasa BEAM
- Opsi kompiler baru
:module_definitionmemungkinkan pemilihan cara eksekusi definisi module dengan nilai default:compiledatau:interpreted, dan dapat diaktifkan lewatmix.exsdenganelixirc_options: [module_definition: :interpreted] - Opsi
:module_definitiontidak memengaruhi file.beamyang ditulis ke disk dan hanya mengubah cara eksekusi di dalamdefmodule, sehingga dapat membantu meningkatkan waktu kompilasi pada proyek besar - Signature tipe baru yang memanfaatkan set-theoretic types akan dibahas bersama definisi typed struct setelah riset terkait performa sistem tipe v1.20, tipe rekursif, tipe terparametrisasi, dan iterasi key-value map terpenuhi
1 komentar
Komentar Hacker News
Mungkin ini hanya pengalaman pribadi, tetapi rasanya bahasa yang sejak awal tidak punya tipe tidak akan bekerja sebaik bahasa dengan tipe statis sungguhan
Saya sudah bekerja sekitar 10 tahun sebagai pengembang Elixir profesional, dan sudah lama menantikan hadirnya tipe. Senang sekali akhirnya langkah awal itu benar-benar masuk kali ini
Namun, saya ingin tahu bagaimana kondisi yang masuk di v1.20 ini dibandingkan dengan Dialyzer tanpa spesifikasi. Sejauh yang saya pahami, pendekatan success typing Dialyzer lebih dekat ke “jika ada setidaknya satu kombinasi argumen yang berhasil, maka tidak akan ada peringatan”, bukan “jika ada kombinasi argumen yang bisa gagal, maka beri peringatan”, dan saya kira yang dilakukan Elixir di sini juga mirip, sementara saya sendiri tidak terlalu merasa Dialyzer sangat berguna
Saya sudah beberapa kali melihat tulisan tentang sistem tipe gradual Elixir di HN, tetapi belum mengikutinya secara detail. Saya penasaran apakah ada yang tahu apakah sistem tipe gradual ini bisa mengubah kompleksitas asimtotik program dibandingkan kode tanpa tipe
Setahu saya, kebanyakan sistem tipe gradual, misalnya Racket, bisa membuat program menjadi lebih lambat secara asimtotik, meskipun ada beberapa pengecualian [1]
[1] https://doi.org/10.1145/3314221.3314627
Kebanyakan sistem tipe gradual menyisipkan enforcement saat nilai melintasi batas antara kode bertipe dan tidak bertipe. Misalnya dengan memeriksa semua elemen daftar, atau membungkus nilai dengan proxy tipe. Namun tim Elixir mempublikasikan hasil strong arrows untuk mendapatkan soundness tanpa pemeriksaan runtime semacam itu, dan bytecode yang dihasilkan compiler secara semantik identik dengan kode tanpa tipe
Ironisnya, para pengkritik bilang tipe itu perlu, dan para penggemar Elixir bilang tipe tidak perlu serta Elixir entah bagaimana seperti sihir sehingga bug terkait tipe tidak terjadi. Sekarang setelah tipe ditambahkan, ternyata justru menemukan bug. Bukannya dulu dibilang tidak perlu untuk mencegah bug? Meski begitu, ini perubahan yang bagus. Dulu saya cukup banyak memakai Elixir dan menikmatinya, tetapi sulit setuju dengan ketiadaan tipe
https://en.wiktionary.org/wiki/Goomba_fallacy
Saya tidak setuju dengan sudut pandang itu, tetapi itu jauh lebih bisa dipertahankan daripada klaim “$LANGUAGE itu sihir”
Sebelum teori tipe himpunan berkembang, mungkin posisi itu memang benar
Lalu pada akhirnya mereka menambahkan tipe statis. Ini terjadi pada Python, JavaScript, dan Ruby, dan mungkin ada lagi yang lain
Saya sangat suka bisa memperbarui Elixir tanpa ada perubahan yang merusak di berbagai proyek, dan compiler secara gratis menemukan bug. Saya sampai terlalu terbiasa dengan hal itu
Saya benar-benar senang melihat ini. Sekarang makin mendekati level “bahasa yang hebat”, dan bagi saya Elixir adalah kandidat nomor satu
Kalau ada bahasa lain yang sudah nyaman dipakai dan terus menambahkan fitur-fitur hebat secara stabil dan aman seperti ini, saya akan sangat berterima kasih kalau diberi tahu. Saya sempat mendalami Go lalu beralih ke mempelajari C# tingkat lanjut, dan rasanya Go berhenti menambahkan fitur bagus
Selama sebulan terakhir saya mencoba track Elixir di exercism.io https://exercism.org/tracks/elixir
Benar-benar luar biasa
Ah, mulai lagi nih. Sepertinya aku bakal belajar Elixir lagi selama setahun ke depan
Aku suka semua hal tentang Elixir, tapi dibanding bahasa lain mana pun, Elixir terus membuatku meragukan diriku sendiri. Sepertinya otakku tidak cocok untuk paradigma fungsional, tapi perubahan ini membuatku ingin mencoba lagi
Yang disayangkan, ekosistemnya sulit dibilang ramah untuk pemula, dan saat menjawab pertanyaan orang sering berasumsi bahwa penanyanya sudah sangat paham bahasanya
Jangan tertipu judulnya. Setengah bagian awal buku itu pada dasarnya hanya tentang Elixir
Selama 8 tahun terakhir, setiap kali aku perlu membiasakan diri lagi dengan Elixir, aku memakai buku ini, dan selalu berhasil. Aku belum pernah membacanya sampai selesai
Salah satu ukuranku untuk menilai apakah buku pemrograman bergaya proyek tutorial seperti ini bagus adalah apakah, meski sudah beberapa kali mulai tapi tidak pernah tamat, di sekitar pertengahan buku aku sudah punya cukup alat untuk kembali mengerjakan pekerjaanku sendiri
Tapi menurutku ini bukan karena otakku tidak cocok, melainkan karena kontras antara tingkat pengalaman yang sudah terkumpul di bahasa imperatif dan kenyataan bahwa dalam gaya fungsional murni kita harus mulai lagi sebagai pemula
Ini akan membaik seiring waktu. Titik balik yang membuatku nyaman dengan pemrograman fungsional adalah saat aku menyadari betapa sukanya aku menyusun kode mirip Bash “one-liner” yang diberi spasi longgar. Jika data dimulai dalam bentuk tertentu, aku dump dengan sebuah perintah, memikirkan tahap yang membuatnya lebih dekat ke bentuk yang kuinginkan, lalu mem-pipe-nya ke perintah berikutnya, lalu melihat lagi. Kalau terus begitu, pada akhirnya yang tersisa biasanya adalah rangkaian transformasi data yang tidak mengubah data secara langsung
Salah satu alasan ini terasa nyaman di shell adalah karena kita setiap hari menjelajahi file system sambil menambah kosakata perintah. Pustaka “fungsi” yang familier di lingkungan mirip Unix sudah tumbuh cukup besar selama bertahun-tahun. Di lingkungan pemrograman fungsional murni kita harus melakukan hal yang sama, hanya saja perlu sedikit lebih banyak usaha untuk mempelajari kosakatanya. “Perintah” yang sering dipakai menjadi fungsi seperti
map,fold,zipalih-alih grep, cat, sortTapi intinya benar-benar sama, dan daya tarik membangun pipeline berlaku sama di keduanya. Kita bisa membangunnya sepotong demi sepotong, dan untuk tiap potongan teka-teki kita bisa melupakan tahap sebelumnya lalu hanya memikirkan bagaimana mengubah data di depan mata ke bentuk berikutnya. Konteks yang rendah ini terasa segar dan nyaman
Semoga kamu mencobanya dan menikmatinya. Saat kamu bisa menikmati keadaan belum bisa melakukan sesuatu, pada akhirnya kamu akan benar-benar mahir
Tentu saja ini baru berdasarkan beberapa sore mencobanya, tapi kalau aku harus melatih otakku lagi ke bahasa fungsional, aku rasa aku akan memilih Gleam karena faktor keakrabannya
Kadang ada tulisan yang terlalu samar sehingga tidak mendapat perhatian, atau diabaikan karena tercium seperti “kerjakan PR-ku”
Tapi postingan yang berisi rasa ingin tahu yang tulus, setahuku, semuanya mendapat jawaban
Keren. Di 1.20, kompilasi aplikasi umbrella besar kami tampaknya jadi lumayan lebih cepat
Penasaran bagaimana perbandingannya dengan Gleam. Atau sekarang kenapa orang harus memakai Elixir alih-alih Gleam? Phoenix, terutama LiveView, sepertinya memang daya tarik besar Elixir
Aku tidak tahu keadaan Gleam OTP saat ini, tapi terakhir kali aku lihat, kondisinya belum bagus
Kalau kamu tidak peduli yang mana dan yang penting hanya tipe, pakai saja Gleam. Tapi kalau begitu, bukankah lebih baik pakai Rust saja?
Misalnya, di Gleam, decoding/encoding JSON bisa jadi bertele-tele. Di Rust kamu bisa derive serde, dan di Elixir cukup satu pemanggilan fungsi
Elixir punya ekosistem yang lebih matang. Misalnya kamu bisa memakai Phoenix atau framework Gleam lain dari Gleam, tapi pengalamannya tidak sama
Alasan besar Gleam lebih menarik daripada Elixir adalah tipe, dan sekarang Elixir mulai memperkecil jarak itu. Ada juga fakta bahwa Gleam bisa dikompilasi ke JavaScript, sementara di Elixir ada Hologram yang melakukan hal serupa
Secara pribadi, aku lebih suka sistem tipe Gleam dan sintaks yang mirip Rust, tapi saat ini Elixir terasa sebagai pilihan yang lebih baik untuk semua proyek pengembangan web milikku