ProgramlamaSistem Rust Geliştiricisi

Rust'ta sabit hesaplama (const evaluation) nasıl çalışır? const, static ve let arasındaki farklar nelerdir, ne zaman (ve neden) const fn kullanılmalıdır ve derleme aşamasında hesaplamalar yazarken hangi sınırlamalar vardır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Rust'ta sabit hesaplama, bazı hesaplamaların veya başlatmaların programın çalışması sırasında değil, derleme aşamasında gerçekleştirilmesini sağlar.

  • const, bellek adresi olmayan ve derleme aşamasında hesaplanan değişmez bir sabiti tanımlar:
const PI: f64 = 3.1415;
  • static, belirli bir bellek segmentinde (genellikle .data veya .bss) bulunan küresel bir değişkeni tanımlar, değiştirilebilirlik mümkündür (unsafe gerektirir):
static mut GLOBAL_COUNTER: i32 = 0;
  • let, yığın üzerinde değişkenler için kullanılır, bunların değeri runtime'da hesaplanabilir ve ilk kullanımdan önce başlatılmaları gerekir.

const fn, sonucunun const veya static değerini belirlemek için kullanılabilen bir işlevdir. Bu tür işlevler sabit bir bağlamda çağrılabilir.

const fn factorial(n: usize) -> usize { if n == 0 { 1 } else { n * factorial(n - 1) } } const FACT_5: usize = factorial(5); // Derlenir!

const fn kısıtlamaları:

  • Sadece başka const fn'ler kullanılabilir,
  • Heap tahsisi (Box::new gibi) kullanılamaz,
  • Güvensiz işlemler çağrılmamalıdır,
  • Harici değişkenlere ve işlevlere (const fn olmayanlar dışındaki) erişim yoktur.

Kandırmaca soru.

Soru: Bir fonksiyonun sonucu değişmiyorsa, herhangi bir fonksiyonu const bağlamında kullanabilir miyiz? Örneğin şöyle:

fn add(a: i32, b: i32) -> i32 { a + b } const RES: i32 = add(1, 2);

Tipik yanlış cevap: Evet, çünkü fonksiyon saf ve sonucu önceden biliniyor.

Doğru cevap: Hayır, fonksiyonun kesin olarak const fn olarak tanımlanması gerekir, yalnızca o zaman sabit başlatma içinde çağrılabilir. Normal fonksiyonlar yalnızca çalışma zamanında çağrılır!

Örnek:

const fn add(a: i32, b: i32) -> i32 { a + b } const RES: i32 = add(1, 2); // Derlenir!

Konuyla ilgili bilgi eksikliğinden kaynaklanan gerçek hata örnekleri.


Hikaye

Üç boyutlu geometri hesaplamaları yapan bir projede, geliştirici değer tablosunu normal bir fonksiyonun sonuçlarıyla değil, const fn ile tanımlamaya çalıştı. Sonuç olarak, derleme hataları oluştu ve derleme zamanı hesaplamalarının avantajı kaybedildi.


Hikaye

Küresel bir önbellek için static mut kullanımı, birden fazla iş parçacığından erişim sırasında veri koşmasına yol açtı (static mut güvenli değildir!). Küresel kaynağa erişimi senkronize etmek için Atomic veya Mutex kullanmak gerekiyordu.


Hikaye

Büyük dizilerin başlatılmasını hızlandırma çabasıyla bunları static olarak tanımladık, ancak static'in her zaman sabit bir adresi olduğunu unuttuk. Bu nedenle veriler, yerel olarak önbelleğe alınmadı ve sunucu mantığında sıcak yol operasyonları yavaşladı. Runtime'da hesaplamalarla yerel let ifadeleri kullanmak gerekiyordu.