- F# 9 yang disertakan dalam .NET 9 mengurangi masalah keamanan yang muncul dalam interoperabilitas C#/.NET melalui nullable reference types dan peningkatan diagnostik compiler
- Properti
.Is*pada discriminated union, partial active pattern yang mengembalikanbool, serta computation expression kosong membuat sintaks F# sehari-hari menjadi lebih ringkas - FSharp.Core menambahkan fungsi acak untuk koleksi dan dukungan collection expression C#, sehingga koleksi immutable F# lebih mudah digunakan juga di kode .NET lain
- Compiler mengungkap lebih dini masalah seperti penggunaan attribute yang keliru, method IL yang melebihi 65.520, dan visibilitas private member
- Dengan optimisasi pemeriksaan equality, rentang integer, serta list/array comprehension, sebagian loop menjadi 1,25×~8×, dan sebagian array comprehension hingga 10× lebih cepat
F# 9 yang disediakan di .NET 9
- F# 9 mencakup perubahan untuk membuat program lebih aman, lebih tangguh, dan lebih berkinerja
- Dapat digunakan di .NET 9, dan .NET SDK terbaru bisa diperoleh dari halaman unduhan .NET
- Perubahan utama dikembangkan di F# open source code repository
Perubahan fitur bahasa
-
Nullable reference types
- F# dirancang untuk menghindari
null, tetapi saat digunakan bersama library .NET yang ditulis dengan C#,nullbisa masuk - F# 9 mengekspresikan reference type yang valid bernilai null secara type-safe, seperti
string | null - Jika memasukkan
nullkestringatau langsung mengakses.Lengthdari nilaistring | null, akan muncul peringatan kemungkinan null - Jika case
nullditangani lebih dulu dalam pattern matching, binding setelahnya diperlakukan sebagai nilai non-null - Dalam kode generik, untuk mengembalikan
nulldiperlukan constraint reference type seperti'T : not struct - Detailnya dapat dilihat di Nullable Reference Types in F# 9
- F# dirancang untuk menghindari
-
Properti
.Is*pada discriminated union- Discriminated union memiliki properti
.Is*yang dibuat otomatis untuk setiap case - Misalnya, jika tipe
Contactmemiliki caseEmaildanPhone, Anda bisa memeriksa apakah itu case tertentu denganperson.contact.IsEmail - Sebelumnya, untuk pemeriksaan yang sama perlu menulis kode seperti
Email _ -> true | _ -> falsedengan ekspresimatch
- Discriminated union memiliki properti
-
Partial active pattern yang mengembalikan
bool- Partial active pattern sebelumnya harus mengembalikan
Some ()saat pencocokan berhasil danNonesaat gagal - Di F# 9, pengembalian
booljuga diizinkan - Dalam contoh pencocokan string tanpa membedakan huruf besar-kecil, hasil
String.Equals(..., StringComparison.OrdinalIgnoreCase)bisa dikembalikan apa adanya
- Partial active pattern sebelumnya harus mengembalikan
-
Extension method diprioritaskan saat ada argumen
- Sebagian library .NET mendefinisikan extension method dengan nama yang sama seperti properti bawaan suatu tipe
- F# 9 menyesuaikan pola ini: ketika argumen diberikan, ia menafsirkan extension method alih-alih gagal saat type checking
- Dalam contoh, extension method
X(f: Foo, i: int)yang namanya sama dengan propertiXmilikFoodapat dipanggil dalam bentukf.X(1), sehingga pengaturan properti dan chaining pemanggilan bisa dilakukan
-
Computation expression kosong
- F# 9 mendukung computation expressions kosong
seq { }membuat sequence kosong, dan dalam kode seperti HTML DSL dapat mengekspresikan blok kosong sepertip { }- Computation expression kosong mengarah ke pemanggilan method
Zeromilik builder - Ini adalah sintaks yang lebih natural dibanding
builder { () }sebelumnya
Peningkatan hash directive dan F# Interactive
-
Argumen hash directive non-string
- Hash directive compiler sebelumnya hanya mengizinkan argumen string yang diapit tanda kutip
- Di F# 9, directive dapat menerima argumen bertipe apa pun
- Anda bisa menulis
#nowarn 0070alih-alih#nowarn "0070", dan#time onalih-alih#time "on"
-
#helpyang diperluas di F# Interactive- Directive
#helpdi F# Interactive menampilkan dokumentasi objek atau fungsi di REPL - Argumen dapat diberikan tanpa tanda kutip
- Misalnya,
#help List.map;;menampilkan deskripsi, parameter, nilai balik, contoh, nama lengkap, dan informasi assembly - Detailnya dapat dilihat di Enhancing #help in F# Interactive blog post
- Directive
-
Prefiks
FSdiizinkan pada#nowarn- Sebelumnya, penulisan seperti
#nowarn "FS0057"menyebabkan errorInvalid warning number 'FS0057'meski nomor peringatannya benar - Di F# 9, nomor peringatan diizinkan meski memiliki prefiks
FS #nowarn 57,#nowarn 0057,#nowarn FS0057, serta bentuk string"57","0057","FS0057"semuanya berfungsi- Di dalam proyek, sebaiknya pertahankan gaya yang sama
- Sebelumnya, penulisan seperti
Peningkatan keamanan dan diagnostik compiler
-
Peringatan posisi
[<TailCall>]yang keliru- F# 9 mengeluarkan peringatan jika attribute
[<TailCall>]ditempelkan pada posisi yang tidak sesuai - Contohnya mencakup kasus ditempelkan pada fungsi non-rekursif, nilai let binding, dan nilai recursive let binding
- Attribute seperti ini tidak memengaruhi perilaku kode, tetapi bisa membingungkan pembaca
- F# 9 mengeluarkan peringatan jika attribute
-
Penerapan
AttributeTargetsdiperketat- Compiler menegakkan
AttributeTargetsdengan benar pada nilai let, fungsi, deklarasi union case, constructor implisit, struct, dan class - Ini dapat mencegah bug yang sulit terlihat, seperti lupa menambahkan argumen unit dalam pengujian Xunit
- Sebelumnya,
[<Fact>] let ``this test always fails`` = Assert.True(false)bukan fungsi sebenarnya sehingga diabaikan oleh test runner, dan lolos saatdotnet testdijalankan - Sekarang muncul error
error FS0842: This attribute is not valid for use on this language element
- Compiler menegakkan
-
Pemulihan parser
- Peningkatan pemulihan parser membuat fitur tooling seperti syntax highlighting tetap bekerja saat kode yang sedang diedit belum lengkap secara sintaksis
- Target pemulihan mencakup pattern
asyang belum lengkap, object expression, deklarasi enum case, deklarasi record, pattern primary constructor yang kompleks, unresolved long identifier, clause match kosong, serta field union case dan tipe field yang hilang
-
Akurasi pesan dan lokasi diagnostik
- F# 9 menambahkan pesan diagnostik baru dan lokasi diagnostik yang lebih akurat
- Targetnya mencakup method override yang ambigu pada object expression, abstract member dalam class non-abstract, properti dengan nama yang sama seperti case discriminated union, ketidaksesuaian jumlah argumen active pattern, union dengan field duplikat, penggunaan
use!danand!bersama dalam computation expression, dan lainnya - Class dengan method yang melebihi 65.520 dalam IL yang dihasilkan akan memunculkan error compile-time baru
- Class seperti ini tidak dapat dimuat oleh CLR, sehingga akan berujung pada error runtime
-
Opsi visibilitas nyata
- F# memiliki karakteristik mencatat private member sebagai internal di IL, sehingga proyek non-F# yang dapat mengakses proyek F# melalui
InternalsVisibleTobisa mengakses private member secara tidak semestinya - F# 9 menyediakan flag compiler
--realsig+sebagai opsi opt-in untuk memperbaiki perilaku ini - Di
.fsproj, fitur ini dapat digunakan dengan menambahkan<RealSig>true</RealSig> - Anda dapat memeriksa apakah solusi bergantung pada perilaku lama
- F# memiliki karakteristik mencatat private member sebagai internal di IL, sehingga proyek non-F# yang dapat mengakses proyek F# melalui
Perubahan standard library FSharp.Core
-
Fungsi acak untuk koleksi
- Modul
List,Array, danSeqmenambahkan fungsi sampling acak dan shuffle - Penggunaan F# menjadi lebih mudah dalam skenario umum yang membutuhkan randomness, seperti data science, machine learning, dan pengembangan game
- Semua fungsi memiliki tiga varian
- Varian yang menggunakan instance
Randombersama yang implisit dan thread-safe - Varian yang menerima instance
Randomsebagai argumen - Varian yang menerima fungsi
randomizerkustom yang harus mengembalikan nilaifloatdari 0.0 hingga kurang dari 1.0
- Varian yang menggunakan instance
- Fungsi yang disediakan adalah empat fungsi:
Shuffle,Choice,Choices, danSample, masing-masing dengan tiga varian - Daftar lengkap fungsi dan variannya dapat dilihat di RFC #1135
- Modul
-
Perilaku tiap fungsi acak
Shufflemengembalikan koleksi baru dengan tipe dan ukuran yang sama, dan setiap item diacak dengan bobot merata terhadap panjang koleksi- Untuk array, ada juga varian
InPlaceyang mengacak item di dalam array yang sudah ada Choicemengembalikan satu elemen acak dengan bobot merata terhadap ukuran koleksiChoicesmemilih N elemen dari koleksi input dalam urutan acak, dan elemen yang sama dapat dipilih beberapa kaliSamplememilih N elemen dari koleksi input dalam urutan acak, tetapi tidak memilih elemen yang sama dua kali- Pada
Sample, N tidak boleh lebih besar dari panjang koleksi
-
Constructor tanpa argumen untuk
CustomOperationAttribute- Constructor tanpa argumen ditambahkan ke
CustomOperationAttribute, sehingga lebih mudah membuat operasi kustom pada computation expression builder - Dalam kebanyakan kasus, nama eksplisit sama dengan nama method, sehingga
[<CustomOperation>]dapat digunakan alih-alih[<CustomOperation("bar")>]
- Constructor tanpa argumen ditambahkan ke
-
Dukungan collection expression C#
- Di C#, list dan set F# dapat diinisialisasi dengan collection expression
- Misalnya, alih-alih
SetModule.FromArray([1, 2, 3]), Anda bisa menulisFSharpSet<int> mySet = [ 1, 2, 3 ]; - Koleksi immutable F# dapat digunakan saat membutuhkan structural equality yang tidak ada pada koleksi
System.Collections.Immutable
Peningkatan performa
-
Optimisasi pemeriksaan equality
- Pemeriksaan equality menjadi lebih cepat dan alokasi memori berkurang
- Contoh mencari nilai yang tidak ada dengan
Array.containspada array tipe struct sebelumnya melakukan boxing 1.000 kali, tetapi sekarang tidak melakukan boxing - Dalam benchmark fungsi array untuk struct 2-member, waktu rata-rata
ArrayContainsNonexistingturun dari 5.190,95ns menjadi 766,005ns, dan alokasi turun dari 24.000B menjadi 0 ArrayTryFindNonexistingturun dari 5.139,58ns menjadi 1.140,515ns, dan alokasi berkurang dari 24.024B menjadi 24B- Detailnya dapat dilihat di F# Developer Stories: How we’ve finally fixed a 9-year-old performance issue
-
Berbagi field pada struct discriminated union
- Jika beberapa case pada struct discriminated union memiliki nama dan tipe field yang sama, field tersebut dapat berbagi lokasi memori yang sama
- Ini mengurangi penggunaan memori struct
- Dalam contoh, ukuran struct discriminated union yang berbagi field berbasis
int64yang sama adalah 16 byte - Versi yang harus memakai nama field unik untuk tiap case seperti cara lama berukuran 60 byte
- Sebelumnya nama field yang sama tidak diizinkan, sehingga tidak ada masalah kompatibilitas biner
-
Optimisasi rentang integer
- Compiler menghasilkan kode yang dioptimalkan untuk lebih banyak kasus ekspresi
start..finishdanstart..step..finish - Sebelumnya, optimisasi hanya berlaku jika tipenya
int/int32dan step adalah konstanta1atau-1 - Tipe integer lain dan nilai step lain menggunakan implementasi berbasis
IEnumerableyang tidak efisien - Sekarang semua kasus seperti ini dioptimalkan
- Pada
for … in start..finish do …,[start..step..finish], dan[for n in start..finish -> f n], terlihat peningkatan kecepatan 1,25× hingga 8×
- Compiler menghasilkan kode yang dioptimalkan untuk lebih banyak kasus ekspresi
-
Optimisasi list dan array comprehension
- Bentuk
for x in xs -> …pada list dan array comprehension dioptimalkan - Peningkatan sangat menonjol terutama pada array
- Kecepatan meningkat hingga 10×, dan ukuran alokasi berkurang menjadi setengah hingga seperempatnya
- Bentuk
Peningkatan tooling Visual Studio
-
Live buffers diaktifkan secara default
- Fitur live buffers di Visual Studio sebelumnya bersifat opt-in, tetapi setelah cukup diuji kini diaktifkan secara default
- Compiler latar belakang yang menggerakkan IDE menggunakan buffer file yang belum disimpan
- Perubahan diterapkan tanpa perlu menyimpan file ke disk
- Sebelumnya, perilaku tak terduga bisa terjadi saat melakukan rename pada simbol yang berada di file yang sudah diedit tetapi belum disimpan
-
Code fix untuk menghapus tanda kurung yang tidak perlu
- Visual Studio menyediakan code fix untuk menghapus tanda kurung yang tidak perlu
- Misalnya,
let f (x) = xdapat diubah menjadilet f x = x, danlet _ = (2 * 2) + 3menjadilet _ = 2 * 2 + 3 - Ini mengurangi kasus saat tanda kurung lebih terasa sebagai noise daripada penjelas
-
Dukungan visualisasi kustom untuk proyek F#
- Debugger visualizer Visual Studio juga berfungsi di proyek F#
-
Signature tooltip di tengah pipeline
- Sebelumnya, jika parameter curried yang kompleks sudah diterapkan pada fungsi di tengah pipeline, signature help tidak tersedia
- Sekarang signature tooltip untuk parameter berikutnya ditampilkan
1 komentar
Komentar Hacker News
F# terus menjadi bahasa favorit saya sejak pertama kali mengenalnya di universitas
F# jauh lebih maju daripada C# dalam fitur seperti union, null safety, pattern matching, record, type inference yang lebih kuat, dan batasan generic
Bagus juga C# akhirnya mengadopsi fitur-fitur seperti ini seiring waktu, tetapi sayang cara masuknya tidak saling kompatibel
Karena investasi pada F# jauh lebih kecil daripada C#, ada sisi yang tertinggal dalam laju inovasi, tetapi F# tetap bahasa yang luar biasa, umumnya kompatibel dengan ekosistem .NET, dan bisa menghasilkan performa yang sama dengan C# dengan boilerplate yang jauh lebih sedikit
Ini cukup mudah ditangani dengan menulis proyek C# pendamping yang berisi “kode perekat” yang diperlukan
Selain itu, saya penasaran apakah ada masalah spesifik lain yang Anda pikirkan
F# 9 juga mendukung penggunaan argumen generic
ref structyang baru-baru ini ditambahkan ke C#, dan setahu saya ada rencana untuk memperkenalkan fitur yang didefinisikan di F# sendiriSejauh ini mereka sudah melakukan pekerjaan mengejar ketertinggalan dengan sangat mengesankan, dan pantas mendapatkan jauh lebih banyak pengakuan
Bagian yang mengatakan “kelas dengan lebih dari 65.520 metode dalam IL yang dihasilkan kini akan memunculkan error compile-time baru. Kelas seperti itu tidak bisa dimuat oleh CLR sehingga menimbulkan error runtime” benar-benar sulit dibayangkan
Bagaimanapun, F# adalah bahasa yang hebat
Menurut saya ini hal terbaik kedua yang pernah Microsoft keluarkan setelah Excel, dan menjadikan .NET sebagai platform yang masuk akal
Relatif mudah diajarkan kepada orang yang sudah terbiasa dengan JS atau TS, dan juga bahasa yang produktif
Dipakai dalam berbagai konteks, mulai dari game engine, backend enterprise, hingga aplikasi desktop
Menurut saya Microsoft sempat melakukan beberapa kesalahan di awal yang memperlambat pertumbuhannya, tetapi sebagai bahasa serbaguna C# benar-benar bagus dan relatif mudah dipelajari
Beberapa tahun lalu saya sempat mencobanya sebentar dengan IDE ringan bernama LINQPad, tetapi setelah itu tidak terus mengikuti kelebihan, kekurangan, atau perkembangannya
https://www.linqpad.net/
Di Phosphor, kami mengambil keputusan besar selama beberapa tahun untuk mempertaruhkan arah perusahaan dan teknologi di atas F#
Setelah mencoba lebih dari setahun, kami menulis ulang aplikasi sepenuhnya dengan TypeScript dan Rust
Produk yang kami buat adalah alat pemrograman untuk pengguna akhir, sehingga batas tradisional frontend/backend menjadi kabur, dan ekosistem .NET tidak cocok untuk itu
Awalnya kami ingin mengompilasi kode F# ke JS, Rust, .NET, dan lainnya dengan Fable agar bisa menjaga type safety di antara berbagai teknologi dan melakukan interoperabilitas yang diperlukan
Dalam praktiknya, interoperabilitas antarberbagai library jauh lebih sulit dari perkiraan, dan mengelola serta memperbarui banyak dependensi dan binding benar-benar menyakitkan
Saya tetap berpikir premis bahwa F# menghasilkan kode yang indah dan efisien itu benar, tetapi dari sisi ekosistem dan cara desainnya, F# menurut saya hanya cocok untuk aplikasi dengan batas frontend/backend tradisional yang jelas
Jika demikian, F# kemungkinan hanya akan dipakai di backend
Teknologi yang paling saya nantikan sekarang adalah Effect dan Moonbit yang kami gunakan secara internal
Library Schema milik Effect menutup banyak celah dalam sistem tipe TS, dan Moonbit terlihat seperti F# modern yang lepas dari ketergantungan MS/.NET
Moonbit dirancang oleh pembuat ReScript, yang bisa dibilang Fable untuk OCaml, dirancang dengan sangat baik, dan dikompilasi langsung menjadi output JS, WASM, dan native yang teroptimasi
Effect sudah kami pakai di lingkungan produksi, sedangkan Moonbit belum, tetapi potensinya sebagai bahasa yang dibuat untuk dunia yang mengutamakan AI cukup luar biasa
Logika bisnis inti dan validator ditulis dalam F#, sementara sisa aplikasi frontend ditulis dengan TypeScript dan backend dengan C#
Dengan kata lain, hanya logika inti dan validasi yang ditempatkan di F#, sedangkan semua input/output ditangani oleh TS dan C#
Saya ingat produknya mirip dan ditulis dengan F#, tetapi saya tidak mengikuti perkembangan terbarunya
Effect cukup bagus, dan saya berharap ada juga untuk bahasa selain TypeScript
MoonBit terlihat seperti bahasa pemrograman proprietary miliknya sendiri, jadi saya agak ragu untuk berpindah ke sana alih-alih bahasa yang sudah dikenal luas; saya penasaran bagaimana Anda melihat bagian itu
Saya pernah mengikuti kelas kriptografi yang membolehkan memilih bahasa apa saja selama memakai .NET, dan tugas yang saya kerjakan dengan F# jauh lebih mudah dibaca daripada milik orang lain
Saya ingin lebih sering memakainya, tetapi pekerjaan data science hampir 100% memakai Python
F# 9 juga mendapat manfaat dari hampir semua peningkatan performa .NET 9 itu sendiri
Terutama peningkatan di sisi object escape analysis yang besar
https://devblogs.microsoft.com/dotnet/performance-improvemen...
Saya benar-benar merindukan masa ketika bekerja dengan F#
Karena ini bahasa yang produktif, mengikuti pembaruannya saja sudah menyenangkan
Mengingat ukuran komunitas dan sikap Microsoft yang kadang tampak tidak peduli, menurut saya dukungan tooling-nya cukup baik
Ketidaknyamanan terbesar adalah akurasi code test coverage
Baru-baru ini saya sempat mencoba F# sedikit, dan sebagai orang yang datang dari Python, saya sangat suka karena bisa bereksperimen macam-macam lewat REPL
Saya penasaran apakah pengembang F# yang berpengalaman juga menggunakannya seperti itu
Musim dingin ini saya ingin membuat proyek web backend kecil untuk lebih mengenal bahasa dan ekosistemnya
Untuk sisi HTTP, saya dengar Oxpecker bagus, tetapi saya penasaran apakah ada rekomendasi klien atau driver PostgreSQL
Saya tidak suka ORM
https://lanayx.github.io/Oxpecker/
https://monazita.gitlab.io/monazita/ dibuat sebagai proyek pribadi sambil belajar F#, pada dasarnya berfungsi tetapi masih ada ruang untuk dipoles, dan khusus PostgreSQL
https://github.com/jacentino/DbFun lebih matang daripada proyek sebelumnya dan mendukung beberapa database
Sebaiknya mulai dari sana
Kalau API-nya belum jelas, bahkan di dalam codebase sebenarnya saya menekan “Send to F# interactive” untuk menjalankan dan bereksperimen di dalam modul
Saya juga memakainya untuk mencoba library baru, melakukan benchmark cepat, atau sebagai pengganti skrip PowerShell
Dengan shebang
#!/usr/bin/env -S dotnet fsi, skrip F# bisa dibuat dapat dieksekusi, jadi saya sering menggunakannya sebagai alternatif bash/Python untuk skrip di sekitar proyek .NET yang sudah memasang dotnet-sdkBiasanya berjalan lebih cepat dan umumnya sama ringkasnya
Secara pribadi, saya merasa sintaks dan idiom F# lebih cocok daripada C# untuk pemrograman REPL yang merangkai potongan-potongan kode kecil
C# biasanya membutuhkan lebih banyak struktur berorientasi objek
Saya penasaran bagaimana versioning F# dilakukan
Ada banyak peningkatan kualitas hidup yang terlihat bagus, tetapi dari sudut pandang semantic versioning tidak ada breaking compatibility sehingga perubahan versi mayor tampaknya tidak terasa dibenarkan, dan untuk proyek yang tidak memakai semantic versioning pun rasanya ini bukan lompatan fitur bahasa yang cukup besar untuk naik dari 8 ke 9
Komentar lain menyebut .NET 9 yang baru dirilis, jadi saya penasaran apakah ini untuk menyelaraskan dengan nomor versi .NET
Saya tidak tahu apakah peralihannya sengaja dilakukan pada momen yang cocok dengan versi .NET, atau hanya kebetulan
Misalnya C# merilis C# 13 untuk menyesuaikan dengan .NET 9
dotnet buildIni mencakup msbuild, compiler, paket NuGet, dan sebagainya
Misalnya tim F# bisa saja merilis perubahan bahasa di antara 8 dan 9, tetapi bahkan jika tidak, mereka tetap bisa merilis perubahan compiler atau perubahan msbuild yang karena alasan tertentu membutuhkan .NET 9
Pengembang biasanya tinggal menaikkan kode ke versi runtime terbaru, kecuali harus menunggu .NET terbaru terpasang di lingkungan deployment
Sekarang kebutuhan itu juga berkurang berkat perubahan MSBuild yang membuat deployment self-contained, tetapi ini tetap hal yang perlu diketahui
Hanya saja C# berada 4 angka di depan
Lagi pula, menurut saya semantic versioning terlalu dibesar-besarkan
Saya penasaran bagaimana keadaan F# sebagai alternatif C# untuk membuat aplikasi GUI di Windows
Saya juga penasaran apakah ada perusahaan yang memakai F# untuk tujuan seperti ini
https://github.com/fsprojects/Avalonia.FuncUI
https://fabulous.dev/ menargetkan Avalonia/MAUI/Xamarin
https://github.com/kekyo/epoxy mendukung Avalonia dan WPF
Kalau tertarik apakah ini dipakai di perusahaan, saya bisa bertanya ke sekitar
Saya belum pernah mencoba F# langsung, tetapi saat melihat-lihat, materi ini tampak sangat bagus: https://fsharpforfunandprofit.com/
Bagus juga untuk pengembang C# berpengalaman maupun orang yang relatif baru belajar pemrograman
Situs ini sekarang hampir tidak diperbarui, jadi sulit menemukan pembahasan fitur baru F# 9, tetapi artikel-artikel lamanya sangat bagus untuk memahami konsep seperti
applydanbind