Go vs. Rust vs. Zig Üzerine Düşünceler
(sinclairtarget.com)- Üç dilin felsefe ve değer anlayışlarındaki farklar odağa alınarak, her birinin hangi sorunları çözmeye çalıştığı karşılaştırılıyor
- Go, sadelik ve istikrarı önceleyen; özellikleri minimumda tutarak iş birliği ve bakımı kolaylaştıran bir dil olarak açıklanıyor
- Rust, güvenlik ve performansı aynı anda hedefliyor; karmaşık tür sistemi ve trait yapısıyla bellek güvenliğini garanti ediyor
- Zig, manuel bellek yönetimi ve veri odaklı tasarım yoluyla geliştiriciye tam kontrol veren deneysel bir dil olarak tasvir ediliyor
- Üç dilin birbirine zıt yaklaşımları, programlama dillerinin hayata geçirdiği değer sistemlerini ortaya koyuyor; seçim ölçütü de geliştiricinin hangi felsefeye yakınlık duyduğu oluyor
Dil karşılaştırısına bakış
- Yazar, işte kullandığı dillerden ziyade, yeni dil denemeleri üzerinden her dilin değer sistemini anlamaya çalışıyor
- Yalnızca özellik listelerini kıyaslamak yerine, dilin hangi ödünleşimleri seçtiğinin önemli olduğunu vurguluyor
- Go, Rust ve Zig işlevsel olarak birçok ortak noktaya sahip olsa da, tasarımcılarının öncelik verdiği değerler farklı
- Her dilin felsefesini kavrayarak, hangi ortam ve amaçlar için uygun olduğuna karar vermek mümkün
Go — sadelik ve iş birliği odaklı dil
- Go, minimalizmiyle ayrışıyor ve “tüm dili kafanda tutabilirsin” özelliğine sahip
- Generics ancak 12 yıl sonra eklendi; tagged union ya da hata işleme için sözdizimsel şeker gibi özellikler hâlâ yok
- Yeni özellik ekleme konusunda çok temkinli; bu yüzden boilerplate kod fazla olsa da dilin istikrarı ve okunabilirliği yüksek
- Go’daki slice, Rust’ın
Vec<T>ya da Zig’inArrayListişlevlerini kapsıyor; bellek konumunu çalışma zamanında sistem otomatik yönetiyor - C++’ın karmaşıklığı ve yavaş derleme sürelerine duyulan tepkiyle yola çıkıp, basit ve hızlı derleme hedefiyle tasarlanmış
- Kurumsal ortamlarda iş birliği verimliliğini önemser; karmaşık özelliklerden çok açık kodu ve tutarlılığı öne koyar
Rust — karmaşık ama güçlü güvenlik ve performans
- Rust, “sıfır maliyetli soyutlama” söylemini benimseyen, çok sayıda kavramı bir araya getiren maksimalist bir dil
- Öğrenmesinin zor olmasının nedeni kavramsal yoğunluğunun yüksek olması; karmaşık bir tür sistemi ve trait yapısı bulunuyor
- Rust’ın temel hedefi, performans ile bellek güvenliğini birlikte sağlamak
- UB (Undefined Behavior) önlemek için derleme zamanında doğrulama yapıyor
- Hatalı pointer referansları veya çift serbest bırakma gibi durumların yol açtığı öngörülemez davranışları engelliyor
- Derleyicinin kodun çalışma zamanı davranışını anlayabilmesi için geliştiricinin türleri ve trait’leri açıkça tanımlaması gerekiyor
- Bu yapı sayesinde başkalarının koduna duyulan güven artıyor ve kütüphane ekosistemi canlı kalıyor
Zig — tam kontrol ve veri odaklı tasarım
- Zig, üç dil arasında en yeni dil; 0.14 sürüm aşamasında ve standart kütüphane belgeleri neredeyse yok
- Manuel bellek yönetimi benimsiyor; geliştiricinin doğrudan
alloc()çağırması ve allocator seçmesi gerekiyor - Rust veya Go’dan farklı olarak, global değişken oluşturmak kolay; çalışma zamanında “illegal behavior” tespit edildiğinde program durduruluyor
- Derleme sırasında seçilebilen 4 farklı release modu ile performans ve güvenlik dengesi ayarlanabiliyor
- Nesne yönelimli programlama (OOP) özellikleri bilinçli olarak dışarıda bırakılmış
- private alanlar veya dynamic dispatch yok;
std.mem.Allocatorbile arayüz olarak uygulanmıyor - Bunun yerine veri odaklı tasarım (data-oriented design) yaklaşımı benimseniyor
- private alanlar veya dynamic dispatch yok;
- Bellek yönetiminde de RAII tarzı ayrıntılı nesne bazlı yönetim yerine, büyük bellek bloklarının periyodik olarak ayrılıp serbest bırakıldığı bir yapı öneriliyor
- Zig, özgür ve karşı-kültürel eğilimleri olan bir dil gibi betimleniyor; OOP düşüncesini ayıklayıp geliştirici odaklı kontrolü en üst düzeye çıkarıyor
- Ekip şu anda tüm bağımlılıkları yeniden yazma çalışmalarına odaklanmış durumda; kararlı sürüm (1.0) içinse henüz bir tarih yok
Sonuç — dillerin ortaya koyduğu değer farkları
- Go’nun merkezinde iş birliği ve sadelik, Rust’ın merkezinde güvenlik ve performans, Zig’in merkezinde ise özgürlük ve kontrol var
- Üç dil arasındaki fark, basit bir özellik karşılaştırmasından çok, yazılım geliştirmeye dair felsefi bir tercihi yansıtıyor
- Geliştiriciler dili, hangi değerlere yakınlık duyduklarına göre seçiyor
1 yorum
Hacker News görüşü
Rust'ta mutable global variable oluşturmak zor değil
Sadece
unsafeya da senkronizasyon sağlayan akıllı pointer'lar kullanmak gerekiyorÇünkü Rust varsayılan olarak re-entrant ve derleme zamanında thread güvenliğini garanti ediyor
Eğer statik thread güvenliğini önemsemiyorsanız, Zig ya da C'deki kadar kolay yapılabilir
Fark şu ki Rust, kodun çalışma zamanı davranışı hakkında daha fazla garanti aracı sunuyor
Başka dillere dönüp bunların bu kadar rahat kullanıldığını görünce, güvenlik açısından delilik gibi geliyor
Ama bu tür “basit işler” birikince hiç de basit kalmıyor
Rust bu çizgiyi zaten geçti ve artık kesinlikle trivial değil
Eğer öyleyse C'den daha cazip görünüyor
İki değişkenin her zaman birlikte kilitlenmesi gereken durumlarda bunun nasıl ele alındığını da bilmek isterim
Debug ederken dönüp dolaşıp sorunun kaynağı hep orası çıkıyordu
Rust'ın kavram yoğunluğunu eleştiren yazı için, pratikte bunların sadece %5'ini bilmenin bile üretken olmak için yeterli olduğunu düşünüyorum
12 yıldan uzun süredir Rust kullanıyorum ama
#[fundamental]gibi bir şeye bir kez bile ihtiyaç duymadımRust'ta arena allocation yapılabiliyor ve allocator kavramı da var
Sadece bir varsayılan allocator bulunuyor ve genelde
Box::newgibi açık heap allocation kullanılıyorMutable global,
static FOO: Mutex<T> = Mutex::new(...)gibi tanımlanabiliyor ve bellek güvenliği için mutex gerekiyorRust'ın type system'i yalnızca bellek güvenliğini değil, kodun anlamsal güvenliğini de garanti edecek şekilde tasarlanmış
C'de bu kadar karmaşıklık yok
Karmaşıklık sonuçta önemli bir mesele
Mesele sadece mümkün olup olmaması değil, temel programlama tarzı farkı
Zig Software Foundation'ın da Asahi Lina'nın Rust hakkındaki sözlerini yanlış aktardığı bir örnek olmuştu
Zig'in başka dilleri küçümseyen pazarlama tavrı pek hoşuma gitmiyor
Zig'i sevmemin nedeni, bellek tükenmesini zarif biçimde ele alabilen bir dil olması
Tüm allocation'ların başarısız olabileceği varsayılıyor ve bunun açıkça ele alınması gerekiyor
Stack alanını da sihirli biçimde yönetmiyor; derleyici çağrı grafiğini analiz ederek azami boyutu tahmin ediyor
Gömülü sistemlerde bu tür kaynak odaklı tasarım şart
Bu, dil düzeyindeki işlemlerle çözülebilecek bir şey değil
Sonuçta yine manuel bellek yönetimi gibi aynı sorunla uğraşıyor
O halde bence bir GC dili kullanmak daha mantıklı
Ancak Rust'ın standart kütüphanesi OOM durumunda panic kullandığı için, gömülü geliştirmeyi destekleyen ayrı bir no-std ekosistemi bulunuyor
Go'nun slice yapısı Rust'taki
Vec<T>ile aynı değilappend()yeni bir slice döndürür; mevcut belleği paylaşabilir de paylaşmayabilir deBelleği küçültmenin bir yolu yoktur ve sadece
append(s, ...)yazarsanız yeni slice'ı görmezden gelmiş olursunuzGo'nun tavrı “dediğimi yap”, Rust'ın tavrı ise “dediğimi yapıp yapmadığını doğrula” gibidir
Yani Go sadelik uğruna hatalara izin verirken, Rust daha karmaşık olmayı göze alıp hataları azaltma yönünü seçiyor
Ayrıca sadece
append(s, ...)yazmak derleme hatası verdiği için, orijinal metin biraz isabetsiz bir iddia içeriyorGo, özellik eklerken karmaşıklığın artmasını dikkatle tartan bir dil
Muhtemelen growable list'leri doğrudan etrafta taşımaya çok sık ihtiyaç duyulmuyor
İnsanlar çoğu zaman sadece dokümantasyonu okumayıp sonra şaşırıyor
C/C++'taki UB (Undefined Behavior) durumlarını çalışma zamanı kontrolleriyle yakalamanın pratikte zor olduğunu düşünüyorum
Android de sanitizer'ları her commit'te uyguladı ama ancak Rust'a geçtikten sonra exploit sayısı azaldı
Diller arası karşılaştırma yazısının her dilin güçlü ve zayıf yanlarını dürüstçe ele alması hoşuma gitti
Sadece Raku'nun anılmaması biraz üzücüydü
Bana göre C–Zig–C++–Rust–Go düşük seviyeli dillerin bir sürekliliğini oluşturuyorsa, yüksek seviyede de Julia–R–Python–Lua–JS–PHP–Raku–WL diye bir çizgi var
Sözdizimi tanımını dil düzeyinde desteklediği için DSL yazmak ya da log parsing yapmak kolay
VM tabanlı olduğundan performansı düşük ama problemin yapısını doğrudan ifade etmek için uygun
Perl'in halefi olarak esnek ama tutarlı bir dil olmayı hedefliyor
Rust'ta bir fonksiyon pointer döndürdüğünde heap allocation'ın otomatik yapıldığını sanmak bir yanlış anlama
Yerel değişkenler stack'te bulunur ve dönüşte yok olur, dolayısıyla pointer geçersiz hale gelir
Rust güvenli modda pointer dereference etmeye izin vermez; unsafe modda ise geçerliliği garanti etme sorumluluğu geliştiriciye aittir
Muhtemelen
Box::newkullanımını “örtük allocation” ile karıştırmışYa kavramlar yanlış anlaşılmış ya da kasıtlı olarak yanıltıcı bir anlatım var gibi görünüyor
Go'nun en büyük artısı basit concurrency modeli
goroutine sayesinde paralel kod yazmak kolaylaşıyor
Interface implementasyonlarını bulmak zor olabiliyor ama okunabilirlik yüksek olduğu için ekip çalışmasına uygun
colored function yok ve channel tabanlı iletişim basit olduğu için doğru concurrency kodunu hızlı yazmak mümkün
İlgili yazı: Structured Concurrency or Go Statement Considered Harmful
std.Ioarayüzü Go'nun concurrency modeline benziyorgoanahtar sözcüğüstd.Io.async, channel'larstd.Io.Queue,selectisestd.Io.selectkarşılığına sahipBenim istediğim şey, Go'nun sadeliğini Rust'ın result/error/enum işleme biçimi ve daha iyi generics ile birleştiren bir dil
OCaml, D, Swift, Nim, Crystal gibi dillere baktık ama hâlâ pazarı domine eden bir örnek çıkmadı
Onun yerine Gleam'e bakılabilir
Bu tür tekrarlayan sorunları çözebilecek bir iyileştirme gelmesini umuyorum
Generics ise muhtemelen hâlâ zor bir mesele olmaya devam edecek
Yazının genel tonu, yeni bir geliştiricinin heyecanını ve merakını hissettirdiği için hoşuma gitti
Go'da generics'in olmaması basit bir minimalizm değil, trade-off'lar üzerine düşünülmüş bir kararın sonucu gibi görünüyor
Rust'taki lifetime birçok kişi için en büyük engeldi ve dilin yenilikçiliği de mevcut kavramların birleşiminde yatıyor
Zig'in manuel bellek yönetimi OOP'yi dışlamaktan çok Data-Oriented Design (DOD) felsefesine dayanıyor
İlgili konuşma: Andrew'un DOD sunumu
esas soru “yavaş programcı, yavaş derleyici, yavaş çalışma zamanı” seçeneklerinden hangisinin seçileceğiydi
Go ekibi sonunda bunu tatmin edici şekilde çözen bir uzlaşma noktası bulmuş görünüyor