Zig comptime'ın olağanüstü olduğu değerlendirmesi
(scottredig.com)- Zig’in derleme zamanı (comptime) metaprogramlaması, çalışma zamanı kodu gibi okunurken; yapı alanlarını toplama gibi tekrarlı kodları, elle yazılmış bir C fonksiyonu kadar verimli çalıştırılabilir koda dönüştürebilir
- Ayrı bir generic söz dizimi yerine
comptime T: typeveanytypekullanarak generic programlama yapması, Zig comptime’ın başlıca kullanım alanıdır - Çalışma zamanı, comptime ve derleme sistemi aynı Zig dilini paylaştığı için, Fizz Buzz gibi bir fonksiyon da derleme sırasında çalıştırılıp önceden hesaplanmış bir diziye dönüştürülebilir
- Derleyici mümkün olan kısımları önce değerlendirir; yalnızca çalışma zamanı değerlerine ihtiyaç duyan kısımları, daha sonra makine koduna dönüşecek çıktı bytecode’u olarak bırakır
- Zig comptime, metinsel kod üretimine benzer sorunları çözebilir; ancak C makroları gibi anahtar sözcükleri keyfi biçimde ikame etmediğinden kod okuma ve hata ayıklama yükünü azaltır
Zig comptime’ı okuma bakışı
- Zig’de comptime bir metaprogramlama özelliğidir; ancak nihai davranışı okurken derleme zamanı ile çalışma zamanı ayrımını çok fazla düşünmek gerekmez
zig zenin üçüncü maddesi olan “Favor reading code over writing code” önemli bir ölçüttür- Makro veya kod üretimi tabanlı metaprogramlama, özgün kod ve genişletilmiş kod diye iki katman oluşturabilir
- Bu dolaylı katmanlar kod okumayı, hata ayıklamayı ve davranışı değiştirmeyi zorlaştırır
[3]i64 = .{1,2,3}dizisinin toplamını hesaplayan çalışma zamanı kodu ileMyStructyapısınına,b,calanlarını toplayan comptime kodu yan yana karşılaştırılırinline for (comptime std.meta.fieldNames(MyStruct))ile alan adları üzerinde dolaşılır- Derleme zamanında bilinen alan adını kullanarak alana erişmek için
@field(my_struct, field_name)kullanılır
- Yapı alanlarını toplama örneği çalışma zamanı reflection’ı gibi görünür; ancak yürütülebilir dosyada, ilgili yapı tipi için toplama fonksiyonu elle yazılmış gibi verimli kod kalır
- Örnekteki dönüşüm süreci Zig uygulamasını birebir yeniden üretmekten çok kavramsal bir açıklamaya yakındır
- Zig çekirdek ekibi, comptime ve çalışma zamanının karıştığı kodu örnekteki gibi adım adım çalıştırabilecek bir debugger üzerinde çalışıyor
Generic’leri comptime ile işleme
- Zig’de ayrı bir generic özelliği yoktur
- Bir tipi generic yapmak için, tip alan bir fonksiyonun tip döndürecek şekilde yazılması gerekir
- Örnek:
pub fn GenericMyStruct(comptime T: type) type - Döndürülen
structına,b,calanlarının hepsiTtipini kullanır
- Örnek:
- Generic fonksiyonlar da aynı yöntemle yazılabilir
- Örnek:
fn quadratic(comptime T: type, a: T, b: T, c: T, x: T) T quadratic(f32, ...)vequadratic(i64, ...)gibi tip argümanı açıkça belirtilebilir
- Örnek:
- Argüman tipi fonksiyon imzasının başka bölümleri için önemli değilse özel tip
anytypeile çıkarım yapılabilir - Bu yöntem tek başına comptime’ın tamamını açıklamaya yetmez; ancak Zig’de yaygın generic işleri anlamak için bir başlangıç noktasıdır
Aynı Zig kodunu derleme zamanında çalıştırma
- Zig, çalışma zamanı, comptime ve derleme sisteminde aynı dili kullanır
- Fizz Buzz örneği,
fizzBuzz(writer)fonksiyonunu önce normal bir çalışma zamanı çıktı fonksiyonu olarak yazar1den100e kadar dolaşır3ve5in katları içinfizzbuzz,3ün katları içinfizz,5in katları içinbuzz, geri kalanlarda sayıyı yazdırır
- Aynı
fizzBuzzfonksiyonu bircomptimebloğu içinde çalıştırıldığında tüm çıktı önceden hesaplanabilirstd.io.countingWriter(std.io.null_writer)ile önce gereken bayt sayısı hesaplanır- Hesaplanan uzunlukla
buffer: [cw.bytes_written]u8dizisi oluşturulur std.io.fixedBufferStream(&buffer)içine yeniden çıktı yazılarakfull_fizzbuzzdeğeri oluşturulur
- Yalnızca kritik bölüm ölçüldüğünde, önceden hesaplanmış sürüm yaklaşık 9 kat daha hızlı çalışır
- Örneğin kendisi küçük olduğundan toplam çalışma süresi başka etkenlerden daha fazla etkilenir
- comptime ile runtime arasında erişilebilen değerler ve özellikler bakımından farklar vardır
comptime_int,comptime_float,typedeğerlerine yalnızca comptime’da erişilebilir- Bazı fonksiyonlar yalnızca comptime argümanları kabul eder ve fiilen comptime’a özel hâle gelir
- Sistem çağrıları veya bunları kullanan özelliklere yalnızca çalışma zamanında erişilebilir
- Bu özel özellikleri kullanmayan kod, comptime ve runtime’da aynı şekilde çalışır
comptime’ı kısmi değerlendirme olarak anlamak
- comptime, derleme sürecinde gerçekleşen kısmi değerlendirme (partial evaluation) olarak görülebilir
- Kısmi değerlendirme; bir fonksiyona argümanların yalnızca bir kısmı verilmişken, sadece zaten bilinen değerleri kullanan ifadeleri önce ikame edip hesaplayarak, geriye kalan bilinmeyen argümanları alan yeni bir fonksiyon oluşturma yöntemidir
- Dizi toplama örneği değerlendirme sürecini adım adım gösterir
fordöngüsü her yinelemenin ayrı ifadelerine ayrıştırılırarray[0],array[1],array[2]sırasıyla1,2,3ile değiştirilirsum0 → 1 → 3 → 6şeklinde güncellenir- Sonunda
std.debug.print(..., .{6})biçimine kadar sadeleşir
- Yapı alanlarını toplama örneği de aynı şekilde okunabilir
inline forcomptime’da çalıştığından"a","b","c"alanları için ayrı ifadelere açılır@field(my_struct, "a"),my_struct.ahâline gelir- Nihai fonksiyon doğrudan
sum += my_struct.a,sum += my_struct.b,sum += my_struct.ciçeren bir biçime dönüşür
- Bu yöntem, niyeti doğrudan kodla ifade ederken alanlar değiştiğinde toplama fonksiyonunu elle güncelleyin diyen yorumlar bırakma ihtiyacını azaltır
Derleme zamanı değerlendirmesi ve çalışma zamanı kodu üretimi
- Zig comptime, derleme zamanı değerlendirmesi ile çalışma zamanı kodu üretiminin birleşimi olarak da görülebilir
- Girdi kodu derleyici tarafından çalıştırılır
- Derleme zamanında bilinebilen ifadeler hemen değerlendirilir
- Çalışma zamanı değerleri gerektiren ifadeler çıktı koduna eklenir
- Bu bakış açısı Zig derleyicisinin gerçek işleyiş biçimine en yakın olandır
- Zig önce söz dizimini ayrıştırır
- Kodu sanal makine için bytecode’a dönüştürür
- VM mümkün olan kısımları değerlendirir; çalışma zamanı işlemesi gerektiren kısımlar ise yeni bytecode olarak yayılır
- Yeni bytecode daha sonra makine koduna dönüştürülür
- Çalışma zamanı girdisi olan
ifgibi koşullu ifadelerde iki yol da üretilir - Ölü kod semantik analizden geçirilmez
- Hatalı bir fonksiyon yazılsa bile gerçekten kullanılana kadar derleme hatası oluşmayabilir
- Bu özellik derlemeyi daha verimli hâle getirir ve
#ifdefolmadan doğal koşullu derlemeyi mümkün kılar
- Zig’de tip adları da comptime’da
typedeğerini değerlendiren ifadelerdir- Fonksiyon argümanı tipi gibi basit görünen tip adları bile comptime değerlendirmesinin sonucudur
- Bu özellik önceki generic örneğini mümkün kılar
- Gerekirse tip daha karmaşık ifadelerle hesaplanabilir
- Zig’in statik analizi, diğer birçok statik tipli dile göre daha karmaşıktır
- Tüm tipleri ortaya çıkarmak için derleyicinin önemli bir bölümünün çalıştırılması gerekir
- Araçlar yetişene kadar kod tamamlama gibi editör özellikleri her zaman iyi çalışmayabilir
Metinsel kod üretimiyle karşılık ilişkisi
- Zig comptime biçim olarak metinsel kod üretiminden farklıdır; ancak benzer sorunları çözebilir
- Kod üretim fonksiyonu
writeSumFn,writer.printilesumFieldsfonksiyonunun kaynak kodunu yazdırır- Üreteçte çalışan kod Zig comptime kısmına karşılık gelir
- Üretecin ürettiği kod çalışma zamanı koduna karşılık gelir
- Zig’in comptime sürümü aynı mantığı daha doğrudan ifade eder
std.meta.fieldNames(MyStruct)ile alan adları elde edilirinline forve@fieldile alan erişim kodu oluşturulur
- Tip bilgisini girdi olarak kullanan kod üretimi Zig’de daha basit hâle gelir
- Metinsel üretim yönteminde tip adı ve alan adı bilgilerinin nereden alınacağı ayrıca çözülmelidir
- Zig’de tipin kendisi ve alan bilgileri comptime’da doğrudan ele alınabilir
- Harici belirtim gibi girdiler kullanılıyorsa dosya içeriği
@embedFileile dahil edilip her zamanki gibi ayrıştırılabilir - Generic yapı örneğinde comptime, tip adı referanslarını metinsel kod üretiminden daha doğrudan ele alır
- Metinsel üretimde
MyStruct_{s}gibi adları string olarak birleştirip tutarlı şekilde eşleştirmek gerekir - comptime’da
GenericMyStruct(T)gibi fonksiyon doğrudan kullanılır
- Metinsel üretimde
- İstisnalar da vardır
- Alan adları comptime’da belirlenen bir tip oluşturulabilir
- Bu durumda alan tanımları listesini içeren bir belirtimle yerleşik fonksiyon çağrılmalıdır
- Böyle tiplerde metot gibi bildirimler tanımlanamaz
- Kodun ifade gücünü kendi başına sınırlamaz; ancak başka koda sunulabilecek API biçimini sınırlar
- C gibi metinsel makrolarla yapılabilen makul işlerin çoğu comptime ile de yapılabilir; ancak kodun görünümü oldukça farklı olabilir
- Zig, metinsel makrolar gibi anahtar sözcükleri başka adlarla değiştirme özelliği sunmaz
Daha fazla okuma ve standart kütüphane örnekleri
- Zig’in kendisi yalnızca comptime’a dayanan bir dil değildir; resmi web sitesinden daha fazlası öğrenilebilir
- Dil referansı comptime’ın somut özelliklerini ele alır
- Zig standart kütüphanesinde comptime kullanım örnekleri vardır
std.debug.printin kullandığı format fonksiyonu güçlü bir generic fonksiyondur- Birçok dil format string’ini çalışma zamanında ayrıştırır ve erken hata yakalama için ayrı doğrulayıcılar ekleyebilir
- Zig, format string’ini comptime’da ayrıştırarak verimli çıktı kodu üretir ve tüm doğrulamaları da derleme zamanında yapar
ArrayListgörece basit ama tam özellikli bir generic container’dır- Zig’in
mainfonksiyonu birden fazla dönüş tipine sahip olabilir ve bu derleyici sihri değil, normal comptime kodu ile işlenir
1 yorum
Hacker News yorumları
Derleme zamanı programlama konusunda hâlihazırda keşfedilmiş sorunları sorgusuz sualsiz övmektense daha derinlemesine ele alınmasını isterdim
Aşamalı programlama yeni değil; Lisp ailesinde de onlarca yıldır benzer şeyler yapılıyor, ancak bu süreçte birçok tasarım ödünü ve sorun ortaya çıktı. Örneğin bu tür generics, parametriklik (parametricity) ilkesini bozarak yalnızca bir fonksiyonun tip imzasına bakıp çıkarım yapmayı zorlaştırıyor. Zig’in özyinelemeli generic tipleri nasıl ele aldığı da belirsiz; tip denetimi ile derleme zamanı hesaplamalarının ne zaman ve hangi sırayla etkileştiği de önemli bir tercih. Yazı, derleme zamanı kodunun yalnızca değerler değil kod da üretebildiğini söylüyor ama hijyen (hygiene) konusunu ele almıyor. İlgili tartışma için https://typesanitizer.com/blog/zig-generics.html iyi bir kaynak
Yine de başka durumlarda Zig kodunda
comptimegörünce “ah…” dediğim zamanlar oluyor. Lisp makroları gibi, aslında hiç var olmayacak ya da kod yapısı daha iyi kurulsa ortadan kalkacak sorunlardan kaçmak için kullanılması kolay. Asıl yazıdaki, struct alanlarını dolaşıp değerleri toplama örneği insanlarıncomptimeı pratikte kullanma biçiminin tipik bir örneği; ancak çoğu durumdastd.enums.EnumArraygibi gerçekten dolaşılabilir bir veri yapısı kullanmak daha iyiTeorik olarak endişe açık, ama pratik dillerde bunun ne kadar önemli olduğu ayrı bir konu. C++ şablonları da şablon özelleştirmesi yoluyla parametrikliği bozar, fakat pratikte bu büyük bir sorun olmaktan ziyade optimizasyonu mümkün kılar. Örneğin
std::vector<bool>gibi her öğeyi gerçekten 1 bit olarak saklayan bir implementasyon, ancak bu tür bir esneklik varsa mümkün olurZig tarzı
comptimeı, daha statik biçimde tanımlanmış fonksiyon imzalarına kıyasla çıkarılabilirlik ile ifade gücü arasında doğrudan bir ödünleşim olarak görüyorum. Yalnızca bu tür çıkarımı tipler üzerinden yapan kodu etkiler ve gerektiğinde seçilebilen bir kısımdır. Tip imzasının yeterli olmadığı durumlarda bile birkaç onlarca satır kaynak kodu okuyunca kullanım biçimi genelde netleşti; uzun süre kafamın karıştığı olmadı. Özyinelemeli generic tip örneklerinde, tanımlanmakta olan adı kullanırsanız “dependency loop detected” alınır ama bunu aşmanın yolları var; yazıdaki generic örneği de kendi kendisine referans veriyor. Tip denetimicomptimesırasında gerçekleşir; örneğin ilk@compileLog("Hi")çalışır, ama ardındanconst a: u32 = "42";satırında tip hatası olursa ikinci log’a kadar gidilmez.comptimeile çalışma zamanı arasındaki tip denetiminde ince sorunlar çıkabilir, ancak bunlar ancak epey anlaşılması güç kodlarda görülür ve kolayca çözülür; çekirdek ekibin de bundan haberdar olduğu için 1.0’dan önce ele alınmasını bekliyorum. Hijyenin tam olarak ne anlama geldiği konusunda daha fazla açıklama gerekiyorBir fonksiyonun net bir mantıksal amacı varsa, adı ve parametre adları iyi verilmişse yalnızca bildirime bakarak da çıkarım yapılabilir. Parametre etiketleri, tip adları gibi programcının belirleyebildiği kısımlar da adın bir parçası sayılabilir. Bağlantısı verilen yazının başlıktaki sonucuna katılıyorum, ancak anlamlı bir argümandan çok puan toplamaya çalışan münazara takımı tarzı bir yazıya yakın. Daha iyi çerçeve esneklik ile karmaşıklık olurdu. Sabit bir generic sistemi iyi tasarlanırsa programlanabilir olana göre daha basit ama daha az esnektir. Zig’in avantajı, metaprogramlama dilinin normal dille neredeyse aynı olması ve bu normal dilin kendisinin de basit olması sayesinde ek karmaşıklık maliyetini azaltması. Yine de derleme zamanı kodu ile çalışma zamanı kodu iç içe geçiyor ve ipuçları az olduğundan, programcının neyin ne zaman çalıştığını ayırt etmesini zorlaştıran bir karmaşıklık ortaya çıkıyor. Dil sunucusu ya da editör eklentilerinin
comptimekoduna farklı bir arka plan rengi veren bir “comptime shader” sunması nasıl olurdu diye düşünüyorumRust deneyimime göre insanların const generics ile yapmak istediği birçok şey,
comptimebenzeri bir özellik olsaydı daha kolay olurdu. Parametrikliği korurken const generics üzerinde aritmetiğe izin vermek implementasyonu zor bir şey; eğer gerçekten istenen “çıktı boyutu N olan bir hash fonksiyonu trait’i” gibi bir şeyse, bu amaç için parametriklikten vazgeçip N’den trait’i daha önceki bir kod üretim aşamasına taşımak kabul edilebilir olabilir. Ama Rust makroları bu şekilde kullanılmak için hem fazla esnek hem de zahmetli. Yine de parametrik polimorfizmi saf bir kod üretim özelliğiyle değiştirdiğiniz anda sıkıntılı yol açılırD’de 17 yıl öncesinden beri vardı. D’nin özellikleri düzenli olarak başka dillere taşındı.
Zig, derleme sırasında çalıştırılacak blokları
comptimeanahtar sözcüğüyle işaretler; D’de ise çalıştırmayı belirleyen bir anahtar sözcük değil, ifadenin sabit ifade olup olmadığıdır. Örneğinint s = sum(3, 4);çalışma zamanında çalışır,enum e = sum(3, 4);ise derleme zamanında çalışır. Sabit olmayan global değişkenlerden, giriş/çıkıştan vemalloc()gibi sistem işlevi çağrılarından kaçınılırsa, pek çok işlev değiştirilmeden derleme zamanında çalıştırılabilir. D’nin otomatik bellek yönetimi sayesinde bellek ayırma da mümkündür.Eskiden statik tablo oluşturmak için ayrı bir program yazılırdı; ama derleme zamanı işlev yürütme sayesinde buna gerek kalmadı.
tytabdizisinin başlangıç değerleri, diziyi hesaplayıp döndüren bir lambda’dan geliyor. Tam örnek https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ba... adresinde. CTFE’nin bir başka yaygın kullanımı da DSL oluşturmaktır.Derleyicinin çalıştığı makine ile programın çalışacağı makine farklıysa D derleyicisi doğruluğu nasıl garanti ediyor? Örneğin
int s = sum(100000, 1000000)değerinin tüm x86 makinelerde aynı olduğunu derleyici nasıl biliyor, merak ediliyor. CPU nesilleri arasında ince farklar olabilir; pratikte host üzerinde yapılan bir hesaplamanın hedef makinede de aynı sonucu vereceği nasıl garanti ediliyor, yoksa mimari aynıysa host ile hedefin yeterince benzer olduğu mu varsayılıyor, merak konusu.int sum(int a, int b) { return a + b; }için_Static_assert(sum(3, 4) == 7, "look ma, check at compile time!");gibi kullanılabiliyor. C standardı bunu neden eklemiyor bilmiyorum; gayet iyi çalışıyor.comptimebağlamında çağırabiliyor.square(2)çalışma zamanı çağrısı,comptime square(3)ise derleme zamanı çağrısıdır.comptimeçağrısı, bir şey derleme zamanı uyumlu değilse derleme hatası üretir; bunun önemli bir özellik olduğunu düşünüyorum. Çünkü derleme zamanında çalışması beklenen kodun, giriş argümanlarındaki değişim nedeniyle kazara çalışma zamanı değerlendirmesine itilmesi durumunda bir uyarı işareti olur.Zig ilginç görünüyor ama operatör aşırı yükleme olmasını isterdim.
Operatör aşırı yüklemeye karşı argümanların çoğu pek ikna edici gelmiyor. İçeride gerçekte ne olduğunun bilinmediği iddiası yeterli değil; sonuçta
addadlı bir işlev de çarpma yapacak şekilde yazılabilir. C++’ıniostreamsveyaboost::spiritörnekleri sık sık kötüye kullanım olarak gösteriliyor; ama operatör aşırı yüklemesi olan diğer dillerde bu pek görülmüyor ve C++’a özgü bir sorun gibi duruyor.OCaml’de operatörler yeniden tanımlanabilir, ama yalnızca başka bir modülün bağlamı içinde. Örneğin
Vec3modülünde+yeniden tanımlandıysaVec3.(a + b + c + d)ya dalet open Vec3 in a + b + c + dşeklinde kullanılabilir. Kaynağı okurken “bu+nereden geldi?” sorusu oluşmaz vea.add(b).add(c).add(d)yazmaktan çok daha iyidir. Ancak Zig artık iyice şekilleniyor gibi; bu tür bir sorunu çözecek büyük bir değişikliğin girmesi zor görünüyor.__işlevlerinin arkasında ne kadar sihir döndüğünü bilemeyebilirsiniz.Zig’in yaklaşımı ferahlatıcı; kodu takip edebilme yeteneği, birkaç karakter daha yazmanın aldığı birkaç saniyeden daha önemli.
İdeal çözüm, dilin aşırı yükleme olduğunu açıkça gösteren kullanıcı tanımlı operatörler sunması olurdu. Örneğin
let c = a |+| bgibi önek/sonek biçiminde bir yapı olursa, koda bakan kişi|+|işleminin aslında bir işlev çağrısı olduğunu anlayabilir. Yine kötüye kullanılabilir, ama temel endişelerden biri azalır.Dil, shading dilleri gibi vektör matematiği sözdizimini doğrudan sağlarsa iyi olabilir. Zig’de en azından Clang’in Vector Extension’ına biraz benzeyen
@Vector()tipi var; ama ne yazık ki Extended Vector Extension değil. Bkz. https://ziglang.org/documentation/master/#Vector ve https://clang.llvm.org/docs/LanguageExtensions.html#vectors-....Böyle bir öneri zaten var mı, emin değilim.
fieldNames, Nim’infieldPairsözelliğine çok benziyor ve son derece kullanışlı bir yapı.Verimli serileştirmeyi çok kolaylaştırıyor; yakın zamanda
fieldPairskullanarak bir tip için iş parçacığı güvenliği derleme zamanı denetimini yaklaşık 20 satırda gerçekleştirdim. Bu tür özelliklerin programlama dillerinde standart özellikler olması gerektiğini düşünüyorum. Rust’ta en çok eksikliğini hissettiğim şeylerden biri bu; son denediğimde tipsiz makrolarla sınırlıydı. Çok kısıtlayıcı. Bir crate’teki struct içinserdeuygulanmış olmasını ummaktan başka çare kalmıyor ve aynı alanlara sahip bir struct’ı programatik olarak doğrudan oluşturmak da mümkün olmuyor.Oldukça üzücü.
serdegibi şeyleri derleme zamanı reflection olsaydı uygulamak çok daha kolay olurdu.Tek ödün, bu tür kütüphaneleri kaynak kod biçiminde dahil etmek zorunda olmaktır.
Belli bir olgunluğa ulaşmış bir C ayrıştırıcı kütüphanesi yazdıktan sonra, dilin kendisinde metaprogramlamanın mutlaka gerekli olduğu iddiasından pek emin değilim
Yapılar, serileştirme, özellikler, ölçümleme vb. üretmek istiyorsanız, kaynak dosyayı işleyip kaynak dosya çıktısı veren sıradan bir C programı yazıp bunu derleme betiğinde önce çalıştırmanız yeterli. Bu meta programların nasıl debug edilip test edildiğini merak ediyorum. Benimki sıradan bir C programı olduğu için diğer kodlarla aynı debugger ve araçları aynen kullanıyor
Derleyicinin kendisi aynı dilde yazıldığı için AST’ye salt okunur erişip C# kaynağı üreten eklentiler ekleyebiliyorsunuz. Debug için iyi bir test framework’ü oluşturmak adına biraz daha çalışma gerekiyor, ama sonrasında standart birim test framework’ü içinde eklentili derleyiciyi çalıştırıp etkileşimli debugger ile inceleyebiliyorsunuz
“C’de rastgele derleme zamanı yürütme:
cl /nologo /Zi metaprogram.c && metaprogram.exe,cl /nologo /Zi program.c. Derleme zamanı kodu native hızda çalışır, debug edilebilir, tamamen prosedüreldir ve keyfidir. Derleyicinin kodu çalıştırmasına gerek yoktur.” https://x.com/ryanjfleury/status/1875824288487571873C’de bunu yapmak için kaynak dosyaları işleyen C programı adına eksiksiz bir C ayrıştırıcısı yazmanız gerekir
Python kodu üreten Python kodu yazıp onu tekrar derletmiştim. Bu kırılgan ve berbat bir karmaşaydı; böyle şeyler yapmak zorunda kalmam Python’dan ayrılmamın büyük nedenlerinden biriydi. Bu, tüm fonksiyon argümanlarını string olarak geçirsen olmaz mı diye sormaya benziyor. String tabanlı kod kullananlar var, ama bu nadir olmalı ve dil bundan kaçınmanın yolunu sunmalı
İlginç bir kalıplardan biri, derleme zamanında yapı oluşturabilmek
PyTorch’ta JSON dosyası oluşturup, Zig’in
@embedFile’ı ile okuyup, belirli birrunmetoduna sahip bir yapı oluşturarak sinir ağını gerçekleştiren bir deney yapmıştım. Teorik olarak derleyicinin sinir ağını doğrudan optimize edebilmesini sağlıyor. Büyük bir avantajını henüz kanıtlayamadım, ama tüm ağın stack üzerinde olması ve dinamik tahsis olmaması da var. Bunun iyi olup olmadığından emin değilimcomptimeyerine Python ile bir kod üreteci yazarak yapmıştımcomptimeZig’in özellikle hızlı olacağından emin değilim ve yapı oluşturan JSON ayrıştırıcısını her seferinde çalıştırmak da istemiyorumİlginç olsa da, böyle durumlarda “D bunu önce yaptı” tarzı yorumlara katılasım geliyor
Zig’in
comptime’ı sizi şaşırttıysa, derleme zamanı kod değerlendirmesi ve tam AST makro sistemi olan Nim’e de mutlaka bakmaya değerDiğer niş dillerle aynı ekosistem sorunları var; buna bir de tartışmalı bir maintainer, uzun süre kalmıyor gibi görünen çekirdek katkıcılar ve bir kripto para şirketinden gelen ana finansman gibi unsurlar ekleniyor. 10 yıl önce bunlar beni rahatsız etmezdi, ama şimdi durum farklı
Nim de istisnalardan uzaklaşmaya çalışıyor gibi görünüyor, ama istisnalar fonksiyonları kirletir ve istisna fırlatan fonksiyonları kullanmasanız bile onları düşünmek zorunda bırakır[1]. Görünmeyen kontrol akışlarıyla uğraşmak için hayat çok kısa. [1]: https://github.com/status-im/nim-stew
Zig genel olarak oldukça iyi bir dil ve gereken işi yapıyor
Amacından sapmaması çok önemli; bu yüzden bazı dillerin sırf kullanılıyor diye her yerde kullanılmasından pek hoşlanmıyorum
Zig’in metaprogramlama yetenekleri ile Rust’ın dev ekosistemini, topluluğunu ve güvenliğini birleştiren bir şey olsaydı keşke
Dil tasarımı açısından Zig’i Rust’tan çok daha fazla seviyorum, ama acemi bir hobi programcısı olarak, en azından şu anda Zig ile gerçekten faydalı ya da güvenilir bir şey yazabileceğime güvenmiyorum
Çünkü derleyici bu tür sorunları derleme zamanında bulmamda yardımcı olmuyordu. Zig’in böyle bir vaat sunmadığını biliyorum, ama benim için belirleyici bir eksik olduğu için Zig bana uygun dil değil gibi. Öte yandan
comptimekavramını Rust makrolarından daha çok seviyorum