Penilaian bahwa comptime Zig sangat unggul
(scottredig.com)- Metaprogramming waktu kompilasi (comptime) Zig dapat dibaca seperti kode runtime, tetapi juga dapat menghasilkan kode eksekusi seefisien fungsi C yang ditulis manual untuk kode berulang seperti penjumlahan field struct
- Alih-alih sintaks generik terpisah, penggunaan
comptime T: typedananytypeuntuk menangani pemrograman generik adalah penggunaan utama Zig comptime - Runtime, comptime, dan sistem build berbagi bahasa Zig yang sama, sehingga fungsi seperti Fizz Buzz pun dapat dijalankan saat kompilasi dan dibuat menjadi array yang sudah dihitung sebelumnya
- Compiler terlebih dahulu mengevaluasi bagian yang memungkinkan, lalu hanya menyisakan bagian yang membutuhkan nilai runtime sebagai bytecode keluaran yang nantinya menjadi machine code
- Zig comptime dapat menyelesaikan masalah yang mirip dengan pembuatan kode berbasis teks, tetapi tidak mengganti keyword secara arbitrer seperti macro C, sehingga mengurangi beban membaca dan debugging kode
Cara membaca Zig comptime
- Comptime Zig adalah fitur metaprogramming, tetapi saat membaca perilaku akhirnya, kita tidak perlu terlalu memikirkan perbedaan antara waktu kompilasi dan runtime
- Butir ketiga dari
zig zen, “Favor reading code over writing code”, menjadi tolok ukur penting- Metaprogramming berbasis macro atau pembuatan kode dapat menciptakan dua lapisan: kode sumber dan kode yang diperluas
- Lapisan tidak langsung seperti ini membuat membaca kode, debugging, dan mengubah perilaku menjadi sulit
- Kode runtime yang menjumlahkan array
[3]i64 = .{1,2,3}dibandingkan berdampingan dengan kode comptime yang menjumlahkan fielda,b,cdari structMyStructinline for (comptime std.meta.fieldNames(MyStruct))digunakan untuk mengiterasi nama field@field(my_struct, field_name)digunakan untuk mengakses field memakai nama field yang diketahui pada waktu kompilasi
- Contoh penjumlahan field struct terlihat seperti reflection runtime, tetapi di executable yang tersisa adalah kode seefisien fungsi penjumlahan untuk tipe struct tersebut yang ditulis manual
- Proses transformasi pada contoh lebih merupakan penjelasan konseptual, bukan reproduksi persis dari implementasi Zig
- Tim inti Zig sedang mengerjakan debugger yang dapat mengeksekusi bertahap kode campuran comptime dan runtime seperti pada contoh
Menangani generik dengan comptime
- Zig tidak memiliki fitur generik terpisah
- Untuk membuat tipe generik, tulis fungsi yang menerima tipe dan mengembalikan tipe
- Contoh:
pub fn GenericMyStruct(comptime T: type) type - Field
a,b,cpadastructyang dikembalikan semuanya menggunakan tipeT
- Contoh:
- Fungsi generik juga dapat ditulis dengan cara yang sama
- Contoh:
fn quadratic(comptime T: type, a: T, b: T, c: T, x: T) T - Argumen tipe dapat dinyatakan eksplisit seperti
quadratic(f32, ...)danquadratic(i64, ...)
- Contoh:
- Jika tipe argumen tidak penting bagi bagian lain dari signature fungsi, tipe khusus
anytypedapat digunakan untuk inferensi - Cara ini saja tidak dapat menjelaskan keseluruhan comptime, tetapi menjadi titik awal untuk memahami pekerjaan generik yang umum di Zig
Menjalankan kode Zig yang sama pada waktu kompilasi
- Zig menggunakan bahasa yang sama untuk runtime, comptime, dan sistem build
- Contoh Fizz Buzz terlebih dahulu menulis fungsi
fizzBuzz(writer)sebagai fungsi output runtime biasa- Mengiterasi dari
1sampai100 - Mencetak
fizzbuzzuntuk kelipatan3dan5,fizzuntuk kelipatan3,buzzuntuk kelipatan5, dan angka untuk sisanya
- Mengiterasi dari
- Jika fungsi
fizzBuzzyang sama dijalankan di dalam blokcomptime, seluruh output dapat dihitung sebelumnya- Pertama menghitung jumlah byte yang dibutuhkan dengan
std.io.countingWriter(std.io.null_writer) - Membuat array
buffer: [cw.bytes_written]u8dengan panjang yang sudah dihitung - Mencetak kembali ke
std.io.fixedBufferStream(&buffer)untuk membuat nilaifull_fizzbuzz
- Pertama menghitung jumlah byte yang dibutuhkan dengan
- Jika hanya bagian inti yang diukur, versi yang sudah dihitung sebelumnya berjalan sekitar 9 kali lebih cepat
- Contohnya sendiri kecil, sehingga waktu eksekusi total lebih banyak dipengaruhi faktor lain
- Comptime dan runtime memiliki perbedaan pada nilai dan fitur yang dapat diakses
- Nilai
comptime_int,comptime_float, dantypehanya dapat diakses di comptime - Sebagian fungsi hanya menerima argumen comptime sehingga pada praktiknya khusus comptime
- System call atau fitur yang menggunakannya hanya dapat diakses saat runtime
- Nilai
- Kode yang tidak menggunakan fitur khusus seperti ini berperilaku sama di comptime dan runtime
Memahami comptime sebagai evaluasi parsial
- Comptime dapat dipandang sebagai evaluasi parsial (partial evaluation) yang terjadi selama proses kompilasi
- Evaluasi parsial adalah cara ketika hanya sebagian argumen diberikan kepada fungsi: ekspresi yang hanya memakai nilai yang sudah diketahui diganti dan dihitung terlebih dahulu, lalu fungsi baru dibuat untuk menerima argumen tersisa yang belum diketahui
- Contoh penjumlahan array menunjukkan proses evaluasi secara bertahap
- Loop
fordipecah menjadi pernyataan individual untuk setiap iterasi array[0],array[1],array[2]masing-masing diganti menjadi1,2,3sumdiperbarui dari0 → 1 → 3 → 6- Pada akhirnya disederhanakan hingga bentuk
std.debug.print(..., .{6})
- Loop
- Contoh penjumlahan field struct juga dapat dibaca dengan cara yang sama
- Karena
inline fordijalankan di comptime, ia dibentangkan menjadi pernyataan individual untuk field"a","b","c" @field(my_struct, "a")berubah menjadimy_struct.a- Fungsi akhirnya memiliki bentuk langsung
sum += my_struct.a,sum += my_struct.b,sum += my_struct.c
- Karena
- Cara ini mengekspresikan maksud langsung di dalam kode, sekaligus mengurangi kebutuhan meninggalkan komentar agar fungsi penjumlahan diperbarui manual ketika field berubah
Evaluasi waktu kompilasi dan emisi kode runtime
- Zig comptime juga dapat dilihat sebagai kombinasi evaluasi waktu kompilasi dan emisi kode runtime
- Kode input dieksekusi oleh compiler
- Pernyataan yang dapat diketahui pada waktu kompilasi langsung dievaluasi
- Pernyataan yang membutuhkan nilai runtime ditambahkan ke kode output
- Sudut pandang ini paling dekat dengan cara kerja nyata compiler Zig
- Zig terlebih dahulu mem-parse sintaks
- Kode diubah menjadi bytecode untuk virtual machine
- VM mengevaluasi bagian yang memungkinkan, dan bagian yang perlu diproses saat runtime dipancarkan sebagai bytecode baru
- Bytecode baru kemudian diubah menjadi machine code
- Conditional seperti
ifyang memiliki input runtime memancarkan kedua jalur - Dead code tidak menjalani analisis semantik
- Bahkan jika menulis fungsi yang salah, error kompilasi mungkin tidak muncul sampai fungsi itu benar-benar digunakan
- Karakteristik ini membuat kompilasi lebih efisien dan memungkinkan kompilasi kondisional yang alami tanpa
#ifdef
- Nama tipe di Zig juga merupakan ekspresi yang mengevaluasi nilai
typedi comptime- Nama tipe yang tampak sederhana, seperti tipe argumen fungsi, juga merupakan hasil evaluasi comptime
- Karakteristik ini memungkinkan contoh generik sebelumnya
- Jika perlu, tipe dapat dihitung dengan ekspresi yang lebih kompleks
- Analisis statis Zig lebih kompleks dibanding banyak bahasa statically typed lain
- Untuk mengetahui semua tipe, sebagian besar compiler harus dijalankan
- Sampai tooling berhasil mengejar, fitur editor seperti code completion tidak selalu bekerja dengan baik
Hubungan dengan pembuatan kode berbasis teks
- Bentuk Zig comptime berbeda dari pembuatan kode berbasis teks, tetapi dapat menyelesaikan masalah serupa
- Fungsi pembuat kode
writeSumFnmencetak source code fungsisumFieldsdenganwriter.print- Kode yang dijalankan di generator berpadanan dengan bagian comptime Zig
- Kode yang dicetak oleh generator berpadanan dengan kode runtime
- Versi comptime Zig mengekspresikan logika yang sama secara lebih langsung
- Mendapatkan nama field dengan
std.meta.fieldNames(MyStruct) - Menyusun kode akses field dengan
inline fordan@field
- Mendapatkan nama field dengan
- Pembuatan kode yang menggunakan informasi tipe sebagai input menjadi lebih sederhana di Zig
- Pendekatan pembuatan teks harus menyelesaikan secara terpisah dari mana mendapatkan informasi nama tipe dan nama field
- Zig dapat menangani tipe itu sendiri dan informasi field secara langsung di comptime
- Jika menggunakan input seperti spesifikasi eksternal, isi file dapat disertakan dengan
@embedFilelalu di-parse seperti biasa - Dalam contoh struct generik, comptime menangani referensi nama tipe lebih langsung daripada pembuatan kode teks
- Pembuatan teks harus merangkai nama seperti
MyStruct_{s}sebagai string dan menjaganya tetap konsisten - Comptime menggunakan fungsi secara langsung seperti
GenericMyStruct(T)
- Pembuatan teks harus merangkai nama seperti
- Ada juga pengecualian
- Tipe yang nama field-nya ditentukan di comptime dapat dibuat
- Dalam kasus ini, fungsi bawaan harus dipanggil dengan spesifikasi yang berisi daftar definisi field
- Deklarasi seperti method tidak dapat didefinisikan pada tipe seperti itu
- Ini tidak membatasi daya ekspresi kode itu sendiri, tetapi membatasi bentuk API yang dapat diekspos ke kode lain
- Sebagian besar pekerjaan masuk akal yang mungkin dilakukan dengan macro teks seperti di C juga mungkin dilakukan dengan comptime, tetapi bentuk kodenya bisa sangat berbeda
- Zig tidak menyediakan fitur untuk mengganti keyword dengan nama lain seperti macro teks
Bacaan lanjutan dan contoh dari standard library
- Zig sendiri bukan bahasa yang hanya bergantung pada comptime, dan Anda dapat mempelajari lebih lanjut di situs web resmi
- Referensi bahasa membahas fitur konkret comptime
- Standard library Zig memiliki contoh penggunaan comptime
- Fungsi format yang digunakan
std.debug.printadalah fungsi generik yang kuat- Banyak bahasa mem-parse format string saat runtime dan dapat menambahkan validator terpisah untuk mendeteksi error lebih awal
- Zig mem-parse format string di comptime untuk membuat kode output yang efisien dan melakukan semua validasi saat kompilasi
ArrayListadalah container generik yang relatif sederhana tetapi berfitur lengkap- Fungsi
mainZig dapat memiliki beberapa tipe return, dan ini tidak ditangani oleh magic compiler, melainkan oleh kode comptime biasa
- Fungsi format yang digunakan
1 komentar
Opini Hacker News
Saya berharap isu-isu yang sudah ditemukan dalam pemrograman waktu kompilasi dibahas lebih mendalam, bukan dipuji begitu saja tanpa kritik
Pemrograman bertahap bukan hal baru, dan keluarga Lisp pun telah melakukan hal serupa selama puluhan tahun, tetapi dalam prosesnya banyak kompromi desain dan masalah terungkap. Misalnya, generics dengan cara seperti ini merusak parametricity, sehingga sulit melakukan inferensi hanya dari signature tipe sebuah fungsi. Juga belum jelas bagaimana Zig menangani tipe generik rekursif, dan kapan serta dalam urutan apa pemeriksaan tipe dan komputasi waktu kompilasi saling berinteraksi adalah pilihan penting. Tulisan itu mengatakan kode waktu kompilasi dapat menghasilkan bukan hanya nilai tetapi juga kode, tetapi tidak membahas hygiene. Untuk pembahasan terkait, https://typesanitizer.com/blog/zig-generics.html bagus
Namun dalam situasi lain, ketika melihat
comptimedi kode Zig, kadang saya merasa “ah…”. Seperti macro Lisp, fitur ini mudah dipakai untuk menghindari masalah yang sebenarnya tidak ada, atau yang akan hilang jika struktur kode ditata lebih baik. Contoh di artikel asli yang mengiterasi field struct lalu menjumlahkan nilainya memang tipikal cara orang memakaicomptime, tetapi dalam banyak kasus lebih baik memakai struktur data yang benar-benar bisa diiterasi, sepertistd.enums.EnumArraySecara teoritis kekhawatirannya jelas ada, tetapi seberapa penting itu dalam bahasa praktis adalah perkara terpisah. Template C++ juga merusak parametricity melalui spesialisasi template, tetapi dalam praktik biasanya bukan masalah besar dan malah memungkinkan optimisasi. Misalnya implementasi seperti
std::vector<bool>yang benar-benar menyimpan tiap elemen sebagai 1 bit hanya mungkin dengan fleksibilitas seperti iniMenurut saya
comptimeala Zig adalah kompromi langsung antara kemampuan inferensi vs daya ekspresi dibanding signature fungsi yang didefinisikan lebih statis. Itu hanya memengaruhi kode yang melakukan inferensi semacam itu lewat tipe, dan merupakan bagian yang bisa dipilih sesuai kebutuhan. Bahkan ketika signature tipe saja tidak cukup, biasanya setelah membaca beberapa puluh baris source, cara pakainya menjadi jelas, dan saya tidak pernah bingung lama. Untuk contoh tipe generik rekursif, jika memakai nama yang sedang dideklarasikan akan muncul “dependency loop detected”, tetapi ada cara mengakalinya, dan contoh generik di tulisan itu juga merujuk dirinya sendiri. Pemeriksaan tipe terjadi selamacomptime; misalnya@compileLog("Hi")pertama akan dieksekusi, tetapi jika setelah itu terjadi error tipe padaconst a: u32 = "42";, eksekusi tidak sampai ke log kedua. Masalah halus bisa muncul pada pemeriksaan tipe antaracomptimedan runtime, tetapi biasanya hanya terlihat pada kode yang cukup rumit dan mudah diselesaikan; tim inti juga mengetahuinya, jadi saya berharap akan ditangani sebelum 1.0. Apa persisnya yang dimaksud dengan hygiene masih perlu dijelaskan lebih lanjutJika sebuah fungsi punya tujuan logis yang jelas serta nama dan nama parameter yang baik, deklarasinya saja sudah bisa cukup untuk inferensi. Bagian-bagian yang bisa ditentukan programmer seperti label parameter dan nama tipe juga bisa dianggap sebagai bagian dari nama. Saya setuju dengan kesimpulan pada judul artikel yang ditautkan, tetapi tulisannya terasa lebih seperti tulisan tim debat yang ingin mencetak poin daripada argumen yang bermakna. Kerangka yang lebih baik adalah fleksibilitas vs kompleksitas. Sistem generik yang tetap, jika dirancang baik, lebih sederhana daripada yang dapat diprogram, tetapi kurang fleksibel. Kelebihan Zig adalah bahasa metaprogramming-nya hampir sama dengan bahasa umumnya, dan bahasa umum itu sendiri juga sederhana, sehingga biaya kompleksitas tambahan berkurang. Namun karena kode waktu kompilasi dan kode runtime bercampur serta petunjuknya sedikit, muncul kompleksitas yang membuat programmer sulit membedakan apa yang dieksekusi kapan. Mungkin menarik jika language server atau plugin editor menyediakan “comptime shader” yang memberi warna latar berbeda pada kode
comptimeDari pengalaman dengan Rust, banyak hal yang ingin dilakukan orang dengan const generics tampaknya akan lebih mudah jika ada fitur seperti
comptime. Mengizinkan aritmetika pada const generics sambil mempertahankan parametricity sulit diimplementasikan, dan jika yang sebenarnya diinginkan hanya semacam “trait fungsi hash dengan ukuran output N”, mungkin tidak masalah mengorbankan parametricity untuk tujuan itu dan menjadikan trait pada N sebagai tahap pembuatan kode sebelumnya. Namun macro Rust terlalu fleksibel dan merepotkan untuk dipakai seperti itu. Meski begitu, begitu polimorfisme parametrik diganti dengan fitur pembuatan kode yang naif, jalan penuh kesulitan pun terbukaDi D, ini sudah ada sejak 17 tahun lalu. Fitur D terus berpindah ke bahasa lain
Zig menandai blok yang akan dijalankan saat kompilasi dengan kata kunci
comptime, tetapi di D, yang menentukan eksekusi bukan kata kunci, melainkan apakah itu ekspresi konstanta. Misalnya,int s = sum(3, 4);dijalankan saat runtime, sedangkanenum e = sum(3, 4);dijalankan pada waktu kompilasi. Jika menghindari global non-konstan, input/output, dan pemanggilan fungsi sistem sepertimalloc(), cukup banyak fungsi bisa dijalankan pada waktu kompilasi tanpa perubahan. Berkat manajemen memori otomatis D, alokasi memori juga dimungkinkanDulu, untuk membuat tabel statis, orang menulis program terpisah, tetapi dengan eksekusi fungsi pada waktu kompilasi, itu tidak lagi diperlukan. Nilai inisialisasi array
tytabberasal dari lambda yang menghitung dan mengembalikan array. Contoh lengkap ada di https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ba.... Kegunaan umum CTFE lainnya adalah membuat DSLJika mesin tempat compiler berjalan berbeda dari mesin tempat program akan dijalankan, bagaimana compiler D menjamin kebenarannya? Misalnya, saya penasaran bagaimana compiler tahu bahwa
int s = sum(100000, 1000000)akan bernilai sama di semua mesin x86. Bisa saja ada perbedaan halus antar-generasi CPU; bagaimana menjamin bahwa perhitungan yang benar-benar dilakukan di host akan memberikan hasil yang sama di mesin target, atau apakah diasumsikan bahwa jika arsitekturnya sama maka host dan target cukup mirip?Dengan
int sum(int a, int b) { return a + b; }, bisa dipakai seperti_Static_assert(sum(3, 4) == 7, "look ma, check at compile time!");. Saya tidak tahu mengapa standar C tidak menambahkan ini, dan ini bekerja dengan baikcomptimesquare(2)adalah pemanggilan runtime, sedangkancomptime square(3)adalah pemanggilan pada waktu kompilasi. Pemanggilancomptimeakan menghasilkan error kompilasi jika ada sesuatu yang tidak kompatibel dengan waktu kompilasi, dan saya menganggap ini fitur penting. Sebab ini menjadi sinyal peringatan ketika kode yang diharapkan berjalan pada waktu kompilasi secara tidak sengaja terdorong menjadi evaluasi runtime karena perubahan argumen inputZig terlihat menarik, tetapi saya berharap ada operator overloading
Sebagian besar argumen yang menentang operator overloading tidak terlalu meyakinkan. Klaim bahwa kita tidak tahu apa yang sebenarnya terjadi di balik layar tidak cukup, karena fungsi bernama
addpun bisa dibuat melakukan perkalian.iostreamsatauboost::spiritdi C++ sering dijadikan contoh penyalahgunaan, tetapi hal seperti itu tidak banyak terlihat di bahasa lain yang memiliki operator overloading, dan tampaknya lebih merupakan masalah khas C++Di OCaml, operator bisa didefinisikan ulang, tetapi hanya di dalam konteks modul lain. Misalnya, jika
+didefinisikan ulang di modulVec3, bisa ditulisVec3.(a + b + c + d)ataulet open Vec3 in a + b + c + d. Saat membaca source, tidak ada pertanyaan “+ini berasal dari mana?”, dan ini jauh lebih baik daripadaa.add(b).add(c).add(d). Namun Zig sudah mulai mengeras, jadi perubahan besar untuk menyelesaikan masalah seperti ini tampaknya sulit masuk__Python dan PHPPendekatan Zig terasa segar, dan kemampuan untuk menelusuri kode lebih penting daripada beberapa detik yang dibutuhkan untuk mengetik beberapa karakter tambahan
Solusi ideal adalah bahasa menyediakan operator buatan pengguna yang secara jelas menunjukkan bahwa itu overloading. Misalnya, dengan bentuk prefiks/sufiks seperti
let c = a |+| b, orang yang membaca kode bisa tahu bahwa operasi|+|sebenarnya adalah pemanggilan fungsi. Ini tetap bisa disalahgunakan, tetapi dapat mengurangi salah satu kekhawatiran utamaJika bahasa menyediakan sintaks matematika vektor secara langsung seperti bahasa shading, itu sepertinya baik-baik saja. Zig setidaknya memiliki tipe
@Vector()yang agak mirip dengan Vector Extension milik Clang, tetapi sayangnya bukan Extended Vector Extension. Lihat https://ziglang.org/documentation/master/#Vector dan https://clang.llvm.org/docs/LanguageExtensions.html#vectors-...Saya tidak begitu tahu apakah proposal seperti itu sudah ada
fieldNamesterlihat sangat mirip denganfieldPairsdi Nim, dan merupakan konstruksi yang luar biasa praktisIni membuat serialisasi yang efisien menjadi sangat mudah, dan belakangan saya memakai
fieldPairsuntuk mengimplementasikan pemeriksaan thread-safety pada waktu kompilasi untuk tipe dalam sekitar 20 baris. Saya rasa fitur seperti ini seharusnya menjadi fitur standar bahasa pemrograman. Salah satu hal yang paling saya rindukan di Rust ada di sini, dan terakhir kali saya mencobanya, itu terbatas pada macro tanpa tipe. Terlalu banyak batasannya. Kita hanya bisa berharap struct dari crate sudah mengimplementasikanserde, dan tidak bisa membuat sendiri secara programatis struct dengan field yang samaCukup disayangkan. Hal-hal seperti
serdeakan jauh lebih mudah diimplementasikan jika ada refleksi waktu kompilasiSatu-satunya kompromi adalah library seperti itu harus disertakan dalam bentuk kode sumber
Setelah pernah menulis pustaka parser C yang sudah cukup lengkap, saya jadi tidak begitu yakin dengan klaim bahwa bahasa itu sendiri harus punya metaprogramming
Kalau ingin menghasilkan struct, serialisasi, properti, instrumentasi, dan sebagainya, cukup tulis program C biasa yang memproses file sumber lalu mengeluarkan file sumber, dan jalankan dulu dari skrip build. Saya penasaran bagaimana program-program meta seperti ini di-debug dan diuji. Punya saya adalah program C biasa, jadi memakai debugger dan alat yang sama seperti kode lain
Karena kompiler itu sendiri ditulis dalam bahasa yang sama, kita bisa memasukkan plugin yang mengakses AST secara read-only dan mengeluarkan sumber C#. Untuk debugging, perlu sedikit usaha tambahan untuk membuat framework pengujian yang bagus, tetapi setelah itu kita bisa menjalankan kompiler yang dipasangi plugin di dalam framework unit test standar dan melihatnya dengan debugger interaktif
“Eksekusi arbitrer pada waktu kompilasi di C:
cl /nologo /Zi metaprogram.c && metaprogram.exe,cl /nologo /Zi program.c. Kode waktu kompilasi berjalan pada kecepatan native, bisa di-debug, sepenuhnya prosedural dan arbitrer. Kompiler tidak perlu menjalankan kode untuk Anda.” https://x.com/ryanjfleury/status/1875824288487571873Untuk melakukan itu di C, Anda harus menulis parser C lengkap untuk program C yang memproses file sumber
Saya menulis kode Python yang menghasilkan kode Python, lalu membuatnya dikompilasi lagi. Ini rapuh dan merupakan kekacauan yang mengerikan, dan kebutuhan melakukan hal semacam ini adalah salah satu alasan besar saya meninggalkan Python. Ini mirip seperti bertanya kenapa tidak meneruskan semua argumen fungsi sebagai string saja. Ada orang yang memakai kode berbasis string, tetapi itu seharusnya jarang, dan bahasa harus menyediakan cara untuk menghindarinya
Salah satu pola yang menarik adalah bisa membuat struct pada waktu kompilasi
Saya pernah bereksperimen membuat file JSON di PyTorch, membacanya dengan
@embedFiledi Zig, lalu membuat struct yang memiliki metoderuntertentu untuk mengimplementasikan jaringan neural. Secara teori, ini memungkinkan kompiler mengoptimalkan jaringan neural secara langsung. Saya belum berhasil membuktikan manfaat besar, tetapi seluruh jaringan juga berada di stack sehingga tidak ada alokasi dinamis. Saya belum yakin apakah itu baguscomptimeSaya tidak yakin
comptimeZig akan sangat cepat, dan saya juga tidak ingin menjalankan parser JSON yang menghasilkan struct setiap kaliIni menarik, tetapi dalam kasus seperti ini saya cenderung setuju dengan komentar semacam “D melakukannya lebih dulu”
Kalau Anda terkesan dengan
comptimemilik Zig, Nim yang memiliki evaluasi kode pada waktu kompilasi dan sistem makro AST penuh juga sangat layak dilihatAda masalah ekosistem seperti bahasa niche lain, ditambah maintainer yang menimbulkan pro-kontra, kontributor inti yang tampaknya tidak bertahan lama, serta pendanaan utama dari perusahaan kripto. Sepuluh tahun lalu hal-hal seperti ini mungkin tidak mengganggu saya, tetapi sekarang berbeda
Nim juga tampaknya berusaha menjauh dari exception, tetapi exception mencemari fungsi dan membuat kita tetap harus memikirkannya meskipun tidak memakai fungsi yang melempar exception[1]. Hidup terlalu singkat untuk berurusan dengan alur kontrol yang tidak terlihat. [1]: https://github.com/status-im/nim-stew
Zig secara keseluruhan adalah bahasa yang cukup bagus dan melakukan apa yang dibutuhkan
Sangat penting untuk tidak keluar dari tujuannya, dan karena itu saya kurang suka beberapa bahasa dipakai di mana-mana hanya karena kebetulan sudah dipakai
Saya berharap ada sesuatu yang menggabungkan kemampuan metaprogramming Zig dengan ekosistem, komunitas, dan keamanan Rust yang sangat besar
Dari sisi desain bahasa saja, saya jauh lebih suka Zig daripada Rust, tetapi sebagai programmer hobi yang belum mahir, setidaknya untuk saat ini saya tidak percaya diri bisa menulis sesuatu yang benar-benar berguna atau dapat diandalkan dengan Zig
Karena kompiler tidak membantu menemukan masalah-masalah semacam itu pada waktu kompilasi. Saya tahu Zig memang tidak menjanjikan hal itu, tetapi bagi saya itu kekurangan yang menentukan, jadi sepertinya Zig bukan bahasa yang cocok untuk saya. Di sisi lain, konsep
comptimelebih saya sukai daripada macro Rust