AoC Problemlerini Çözerek Ada ve Rust Karşılaştırması
(github.com/johnperry-math)- Ada ve Rust dilleriyle Advent of Code problemleri çözülürken ortaya çıkan farklar ve özellikler karşılaştırılıyor
- Güvenlik ve güvenilirlik odağındaki bu iki dilin dil tasarımı ile gerçek program yazma biçimleri arasındaki farklar analiz ediliyor
- Her dilin standart kütüphanesi, özelliklerin yerleşik olup olmaması, performans farkları, hata işleme tarzı gibi çeşitli açılardan ayrıştığı görülüyor
- Modülerlik, generic'ler, döngüler, hata yönetimi gibi konularda gerçek kod örnekleriyle, yazım ve işletim sırasında karşılaşılan somut durumlar anlatılıyor
- Statik tip belirtme yaklaşımı, dizi işleme ve hata işleme arayüzlerindeki farkların geliştirici deneyimini belirgin biçimde etkilediği vurgulanıyor
Giriş ve amaç
- Advent of Code(kısaca AoC) problemlerini çözerken başlangıçta yalnızca Ada kullanılırken, 2023'ten itibaren çözümler Rust ve Modula-2 ile de yazılmaya başlanınca doğrudan karşılaştırma yapma imkânı doğdu
- Mevcut Ada merkezli çözümler Rust'a taşınırken iki dilin yapısal farkları ve kendine özgü yaklaşımları doğrudan hissedildi
- Amaç, kod güvenliği, güvenilirlik ve dil tasarımı açısından gerçek kullanım farklarını daha net ortaya koymak
Karşılaştırmada kullanılan dil sürümleri
- Ada 2022 (gerektiğinde Spark 2014'ün bazı kurallarına da başvuruluyor)
- Rust 2021 (ana karşılaştırmalar Rust 1.81.0 sürümü temel alınarak yapılıyor)
Hariç tutulan özellikler ve karşılaştırma ölçütleri
- Her dilin öne çıkan özellikleri (=killer feature) metin içinde kısa yorumlarla anılıyor
- Kişisel deneyim ve çözümlerin pratik gereksinimlerine bağlı olarak ele alınmayan bazı özellikler de var
- Mümkün olduğunca öznel görüşler dışarıda bırakılarak temel özelliklere odaklanılıyor
Yazarın arka planı ve bakış açısı
- Hem Ada hem Rust kullanımı, ana dili bu diller olmayan bir geliştirici perspektifinden; temelinde C/C++, Pascal, Modula-2 gibi 1980'ler dilleri deneyimi var
- Bu nedenle kod stili modern/idiomatik yaklaşımlardan farklı olabilir
- Uygulamalar her zaman en iyi çözüm olmayabilir; bazı durumlarda sezgisel ya da alışılmadık yöntemler seçilmiş olabilir
Ada ve Rust'ın konumlandırılması
- Ada, bugün de son derece güvenli ve güvenilir sistem/gömülü geliştirme dili olarak varlığını sürdürüyor ve kod okunabilirliğine önem veriyor
- Rust, bellek güvenliği ve sistem programlama gücüyle öne çıkıyor; Stack Overflow geliştirici anketlerinde yıllardır 'en sevilen dil' olarak gösteriliyor
- Ada, genel amaçlı yüksek seviyeli bir dil olarak okuma ve bakım tarafında güçlü bir yelpaze sunuyor
- Rust ise düşük seviyeli sistem programları geliştirmeye yöneliyor; açık bellek yönetimi ile hata/seçenek tipleri temelli güvenli programlama kültürü oluşturuyor
Güvenlik ve yapısal özelliklerin karşılaştırması
-
Ada
- ISO standardı mevcut (katı ve ayrıntılı bir spesifikasyon)
- Problemin niteliğine uygun tipleri (aralık, basamak sayısı vb.) tanımlamak kolay
- Dizi indekslerinin sayısal olması şart değil
- Spark adlı daha da katı bir spesifikasyon bulunuyor
-
Rust
- Spesifikasyon daha çok resmi belgeler(Reference) ve derleyici etrafında şekilleniyor
- Tip tanımları makine tiplerine dayanıyor (ör. f64, u32)
- Dizi indeksleme doğal olarak yalnızca sayısal tiplerle yapılıyor
Özellikler / yerleşik destek tablosundan öne çıkanlar
- Dizi sınır kontrolü, generic konteynerler, eşzamanlılık, etiketli döngüler, pattern matching desteği gibi alanlarda farklar bulunuyor
- Ada, hata işleme için Exception(istisna) temelli bir yaklaşım kullanırken Rust, Result/Option tipleriyle dönüş değeri tabanlı bir yöntem izliyor
- Rust; makrolar, pattern matching, fonksiyonel saflık desteği gibi konularda belirgin biçimde ayrışıyor
- Ada, sözleşme tabanlı tasarım ve DBC(Design By Contract) derleme zamanı doğrulamasını Spark üzerinden destekliyor
- Bellek güvenliği açısından Rust ve Spark bunu zorunlu kılarken, Ada null pointer kullanımına izin veriyor
Performans ve çalışma süresi karşılaştırması
- Genel kanı, Rust'ın çalışma zamanında hızlı ama derleme hızında yavaş, Ada'nın ise tersine daha hızlı derlenip çalışma zamanında doğrulama kontrollerine göre biraz daha yavaş olabildiği yönünde
- Benchmark sonuçlarında, Rust day24 probleminde f64 tipinin sınırları nedeniyle taşma yaşarken, Ada digits 18 gibi yüksek seviyeli tip tanımlarıyla uygun makine tipini otomatik seçip taşmadan kaçınarak güçlü performans gösterdi
- Rust tarafında kararsız durumdaki f128 ya da harici kütüphaneler gerekirken, Ada yalnızca derleyici spesifikasyonuna uygun tip tanımıyla avantaj sağlayabiliyor
Dosya işleme ve hata yönetimi (Vaka İncelemesi 1)
Ada'da dosya işleme
- Temelde Ada.Text_IO kullanılıyor
- Dosya açma, satır satır okuma, istenen aralık ve konuma göre satır işleme gibi işler görece sezgisel biçimde yapılabiliyor
- Hata durumunda, açık bir hata mesajından çok istisna fırlatılıyor ve fonksiyon imzasında hata olasılığı görünmüyor
Rust'ta dosya işleme
- std::fs::File ve BufReader kullanılıyor
- Dosya açılışı Result tipi döndürdüğü için hata ihtimali açıkça görülüyor
- Karakterlere doğrudan indeksle erişim yok; mutlaka Iterator ile işlem yapmak gerekiyor
- map, filter, collect, sum gibi fonksiyonel/yinelenebilir araçlar merkezde yer alıyor ve çeşitli makrolar da sunuluyor (ör. include_str!)
- Dönüş tipinde hataların açıkça belirtilmesi sayesinde, hata yayılımı fonksiyon düzeyinde daha net hâle geliyor
Modülerlik ve generic'ler (Vaka İncelemesi 2)
Ada'nın modülerliği
- Paket(package) tabanlı yapı sayesinde belirgin bir spesifikasyon(arayüz) ve gerçekleme ayrımı var
- Modülerliği güçlendirmek için alt paketler ile use/rename sözdizimi birlikte kullanılarak okunabilirlik ayarlanabiliyor
- Paketlerin generic desteği var: tipler, sabitler ve hatta alt paketlerin tamamı genelleştirilebiliyor
Rust'ın modülerliği
- Modüller mod/crate sistemiyle düzenleniyor; spesifikasyon ve gerçekleme ayrımı dokümantasyon üreticileriyle büyük ölçüde otomatikleşiyor
- pub/private erişim belirleyicileriyle bildirime dayalı erişim yetkisi veriliyor
- use/as ile import ve yeniden adlandırma birlikte kullanılabiliyor
- Yerleşik test desteği sayesinde test modülleri doğrudan koda yazılabiliyor, derlenebiliyor ve otomatik çalıştırılabiliyor
Generic'ler
- Ada yalnızca paket/prosedür düzeyinde generic desteği sunuyor (tek başına tipe uygulanamıyor)
- Rust'ta tiplerin kendisine generic uygulanabiliyor (template benzeri yapı)
- Ada, tip aralığı gibi ek özellikleri range type, subtype gibi yapılarla açıkça ifade edebilirken, Rust tarafında örnek sabitler kullanılıyor
Enum tiplerinin karşılaştırılması (Vaka İncelemesi 3)
- Ada, kısa ve sade bir bildirimle birlikte ayrık, sıralı ve döngü/indekslemede kullanılabilir tipleri otomatik olarak sağlıyor
- Rust enum bildirimleri de benzer görünse de, pattern matching ve yineleme gibi kullanım biçimlerinde daha açık seçik ifadeler gerekiyor
Sonuç
- Yüksek seviyeli spesifikasyon tipleri, doğrulanabilirlik ve çalışma zamanı kontrolleri gibi alanlarda Ada daha sıkı bir denetim sunuyor
- Fonksiyonel programlama stili, makro programlama, derleyici destekli hata işleme gibi konularda Rust hem geliştirme kolaylığı hem de güvenlik açısından üstünlük gösteriyor
- Gerçek problem çözümünde Ada, eski kodla uyumluluk ve bakım avantajları sunarken; Rust modern araç ekosistemi ile güvenlik/paralellik desteğinde öne çıkıyor
1 yorum
Hacker News görüşleri
Nim Subranges açıklama bağlantısı
İlgili belge
Rust spec
str::as_bytesile byte slice kullanmak daha doğruPrunt ana sayfası
Prunt GitHub
İlgili HN yorumu
pub const SIDE_LENGTH: usize = ROW_LENGTH;gibi bir sabit tanımı kullanmak daha doğrudan olurIndex<BirdSpecies>uygulayarak) eggs[Robin] yapabilirsiniz, ama eggs[5] hata verir. Yalnız Rust bunu doğrudan dil seviyesinde “dizi” olarak sunmaz. Ada’daki gibi “kullanıcı tanımlı tiplerin bir alt kümesi olan tamsayı tipleri” tanımlanabildiğinde bu indeksleme gerçekten değer kazanıyor. Rust’ta henüz saf kullanıcı tanımlı tiplerle aralık kısıtlı integer’lar oluşturulamıyor (yalnızca dahili olarak NonZeroI16 gibi tipler var). Rust bunu da desteklese harika olurdu