Değişkenler ve Değişkenlik
Cairo, değişmez bir bellek modeli kullanır, yani bir bellek hücresine yazıldığında üzerine yazılamaz, yalnızca okunabilir. Bu değişmez bellek modelini yansıtmak için, Cairo'daki değişkenler varsayılan olarak değişmezdir. Bununla birlikte, dil bu modeli soyutlar ve değişkenlerinizi değişken yapma seçeneği sunar. Cairo'un neden ve nasıl değişmezliği zorladığını ve değişkenlerinizi nasıl değiştirilebilir hale getirebileceğinizi keşfetmeye başlayalım.
Bir değişken değişmez olduğunda, bir değer bir isme bağlandığında, o değeri değiştiremezsiniz. Bu durumu göstermek için, scarb new variables
komutunu kullanarak cairo_projects dizininizde variables adlı yeni bir proje oluşturun.
Ardından, yeni variables dizininde, src/lib.cairo dosyasını açın ve aşağıdaki kod ile değiştirin, ancak henüz derlenmeyecektir:
Filename: src/lib.cairo
fn main() {
let x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
}
Programı kaydedin ve scarb cairo-run
kullanarak çalıştırın. Bu çıktıda gösterildiği gibi, bir değişmezlik hatası ile ilgili bir hata mesajı almalısınız:
$ scarb cairo-run
Compiling no_listing_01_variables_are_immutable v0.1.0 (listings/ch02-common-programming-concepts/no_listing_01_variables_are_immutable/Scarb.toml)
error: Cannot assign to an immutable variable.
--> listings/ch02-common-programming-concepts/no_listing_01_variables_are_immutable/src/lib.cairo:6:5
x = 6;
^***^
error: could not compile `no_listing_01_variables_are_immutable` due to previous error
error: `scarb metadata` exited with error
Bu örnek, derleyicinin programlarınızdaki hataları bulmanıza nasıl yardımcı olduğunu göstermektedir. Derleyici hataları sinir bozucu olabilir, ancak yalnızca programınızın henüz istediğiniz şekilde güvenli bir şekilde çalışmadığı anlamına gelir; bunlar sadece programcıların iyi olmadığı anlamına gelmez! Deneyimli Caironautes hala derleyici hataları alır.
Değişmez x
değişkenine ikinci bir değer atamaya çalıştığınız için Cannot assign to an immutable variable
hata mesajını aldınız.
Bir değeri değiştirmeye çalıştığımızda derleme zamanı hataları almak önemlidir, çünkü bu özel durumlar hatalara yol açabilir. Kodumuzun bir kısmı, bir değerin asla değişmeyeceği varsayımıyla çalışırken, kodumuzun başka bir kısmı bu değeri değiştirirse, kodun ilk kısmının tasarlandığı şekilde çalışmayabileceği bir durum olabilir. Bu tür bir hatanın nedeni, özellikle ikinci kod parçasının değeri sadece sometimes değiştirdiğinde, sonradan takip etmek zor olabilir.
Cairo, çoğu diğer dilden farklı olarak değişmez belleğe sahiptir. Bu, beklenmedik bir şekilde değerlerin asla değişmeyeceği için tüm hata türünü imkansız kılar. Bu, kodun daha kolay anlaşılmasını sağlar.
Ancak değişkenler varsayılan olarak değişmez olsalar da, değişken adının önüne mut
ekleyerek onları değiştirilebilir hale getirebilirsiniz. mut
eklemek aynı zamanda kodun gelecekteki okuyucularına, bu değişkenle ilişkilendirilen değerin diğer kod parçaları tarafından değiştirileceğini belirterek niyeti iletecektir.
Ancak bu noktada, bir değişkenin mut
olarak bildirildiğinde tam olarak ne olduğunu merak ediyor olabilirsiniz, çünkü önceki olarak Cairo'nun belleğinin değişmez olduğunu belirtmiştik. Cevap, değerin değişmez olduğu, ancak değişkenin değişmez olmadığıdır. Değişkenle ilişkilendirilen değer değiştirilebilir. Cairo'da bir değişkenin değiştirilebilir bir şekilde atanması, özünde onu başka bir bellek hücresinde başka bir değere başvuracak şekilde yeniden bildirmekle eşdeğerdir, ancak derleyici bunu sizin için halleder ve mut
anahtar kelimesi bu durumu açıkça belirtir. Düşük seviyeli Cairo Assembly kodunu incelediğinizde, değişken mutasyonunun, mutasyon işlemlerini değişken gölgesine eşdeğer bir dizi adıma çeviren sözdizimsel şeker olarak uygulandığı açık hale gelir. Tek fark, Cairo seviyesinde değişkenin yeniden bildirilmediği ve bu nedenle türünün değişmediği yerdir.
Örneğin, src/lib.cairo dosyasını aşağıdaki şekilde değiştirelim
fn main() {
let mut x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
}
Programı şimdi çalıştırdığımızda şunu elde ediyoruz
$ scarb cairo-run
Compiling no_listing_02_adding_mut v0.1.0 (listings/ch02-common-programming-concepts/no_listing_02_adding_mut/Scarb.toml)
Finished `dev` profile target(s) in 4 seconds
Running no_listing_02_adding_mut
The value of x is: 5
The value of x is: 6
Run completed successfully, returning []
mut
kullanıldığında x
'e bağlanan değeri 5
'ten 6
'ya değiştirmemize izin verilir. Sonuçta, mutabiliteyi kullanıp kullanmamaya karar vermek size bağlıdır ve bu, belirli bir durumda neyin daha net olduğuna bağlıdır.
Sabitler
Değişmez değişkenler gibi, sabitler bir isme bağlanan ve değiştirilmesine izin verilmeyen değerlerdir, ancak sabitler ile değişkenler arasında birkaç fark vardır.
First, you aren’t allowed to use mut
with constants. Constants aren’t just immutable by default—they’re always immutable. You declare constants using the const
keyword instead of the let
keyword, and the type of the value must be annotated. We’ll cover types and type annotations in the next section, “Data Types”, so don’t worry about the details right now. Just know that you must always annotate the type.
Constant variables can be declared with any usual data type, including structs, enums and fixed-size arrays.
Sabitler yalnızca global kapsamda bildirilebilir, bu da onları kodun birçok kısmının bilmesi gereken değerler için kullanışlı hale getirir.
The last difference is that constants may natively be set only to a constant expression, not the result of a value that could only be computed at runtime.
Here’s an example of constants declaration:
struct AnyStruct {
a: u256,
b: u32,
}
enum AnyEnum {
A: felt252,
B: (usize, u256),
}
const ONE_HOUR_IN_SECONDS: u32 = 3600;
const STRUCT_INSTANCE: AnyStruct = AnyStruct { a: 0, b: 1 };
const ENUM_INSTANCE: AnyEnum = AnyEnum::A('any enum');
const BOOL_FIXED_SIZE_ARRAY: [bool; 2] = [true, false];
Yine de, consteval_int!
macrosunu kullanarak bazı hesaplamanın sonucu olan bir const
değişkeni oluşturmak mümkündür:
const ONE_HOUR_IN_SECONDS: u32 = consteval_int!(60 * 60);
We will dive into more detail about macros in the dedicated section.
Cairo'nun sabitler için isimlendirme kuralı, tüm harfleri büyük harf ve kelimeler arasında alt çizgi kullanmaktır.
Sabitler, programın çalıştığı süre boyunca, bildirildikleri kapsam içinde geçerlidir. Bu özellik, sabitleri programınızın birçok kısmının bilmesi gereken uygulama alanınızdaki değerler için kullanışlı hale getirir, örneğin bir oyuncunun kazanabileceği maksimum puan sayısı veya ışığın hızı gibi.
Programınız boyunca kullanılan sabit değerlere sabitler olarak isim vermek, bu değerin anlamını kodun gelecekteki bakımını yapacak kişilere iletmek için kullanışlıdır. Ayrıca, eğer sabit değeri gelecekte güncellenmesi gerekiyorsa, kodunuzda değiştirmeniz gereken tek bir yer olmasına yardımcı olur.
Gölgeleme
Değişken gölgesi, önceki bir değişkenle aynı ada sahip yeni bir değişkenin bildirilmesini ifade eder. Caironautes, ilk değişkenin ikinci tarafından gölgelediğini söyler, bu da ikinci değişkenin, değişkenin adını kullandığınızda derleyicinin göreceği şey olduğu anlamına gelir. Etkide, ikinci değişken birinciyi gölgeleyerek, değişken adının kullanıldığı herhangi bir kullanımı kendisine alır, ya kendisi gölgelenir ya da kapsam sona erene kadar. Bir değişkeni, aynı değişken adını kullanarak ve let
anahtar kelimesini kullanımını tekrarlayarak gölgeleyebiliriz, aşağıdaki gibi:
fn main() {
let x = 5;
let x = x + 1;
{
let x = x * 2;
println!("Inner scope x value is: {}", x);
}
println!("Outer scope x value is: {}", x);
}
Bu program önce x
'i 5
değerine bağlar. Sonra, let x =
'yi tekrarlayarak yeni bir değişken x
oluşturur ve orijinal değeri alır ve 1
ekler, böylece x
'in değeri 6
olur. Ardından, süslü parantezlerle oluşturulan iç içe kapsamda, üçüncü let
ifadesi de x
'i gölgeleyerek yeni bir değişken oluşturur, önceki değeri 2
ile çarparak x
'e 12
değerini verir. Bu kapsam sona erdiğinde, iç içe gölgeleme sona erer ve x
tekrar 6
olur. Bu programı çalıştırdığımızda, aşağıdaki çıktıyı verecektir:
$ scarb cairo-run
Compiling no_listing_03_shadowing v0.1.0 (listings/ch02-common-programming-concepts/no_listing_03_shadowing/Scarb.toml)
Finished `dev` profile target(s) in 4 seconds
Running no_listing_03_shadowing
Inner scope x value is: 12
Outer scope x value is: 6
Run completed successfully, returning []
Gölgeleme, bir değişkeni mut
olarak işaretlemeden farklıdır çünkü bu değişkeni yanlışlıkla let
anahtar kelimesini kullanmadan yeniden atamaya çalışırsak derleme zamanı hatası alırız. let
kullanarak bir değeri birkaç dönüşüm yapabiliriz, ancak bu dönüşümler tamamlandıktan sonra değişken değiştirilemez olur.
mut
ve gölgeleme arasındaki bir başka fark, let
anahtar kelimesini tekrar kullandığımızda etkili bir şekilde yeni bir değişken oluşturuyor olmamızdır, bu da aynı adı yeniden kullanarak değerin türünü değiştirmemize olanak tanır. Daha önce belirtildiği gibi, değişken gölgeleme ve değişkenler de düşük düzeyde eşdeğerdir. Tek fark, bir değişkeni gölgelediğinizde derleyici, türünü değiştirirseniz şikayet etmez. Örneğin, programımız u64
ve felt252
türleri arasında bir tür dönüşümü gerçekleştirirse.
fn main() {
let x: u64 = 2;
println!("The value of x is {} of type u64", x);
let x: felt252 = x.into(); // converts x to a felt, type annotation is required.
println!("The value of x is {} of type felt252", x);
}
Ilk x
değişkeni u64
türüne sahipken ikinci x
değişkeni felt252
türüne sahiptir. Bu nedenle, gölgeleme bize x_u64
ve x_felt252
gibi farklı isimler bulma zorunluluğundan kurtarır; bunun yerine daha basit x
adını yeniden kullanabiliriz. Ancak, bunun için mut
kullanmaya çalışırsak, burada gösterildiği gibi derleme zamanı hatası alırız:
fn main() {
let mut x: u64 = 2;
println!("The value of x is: {}", x);
x = 5_u8;
println!("The value of x is: {}", x);
}
Hata, bir u64
(orijinal tür) beklediğimizi ancak farklı bir tür elde ettiğimizi söylüyor:
$ scarb cairo-run
Compiling no_listing_05_mut_cant_change_type v0.1.0 (listings/ch02-common-programming-concepts/no_listing_05_mut_cant_change_type/Scarb.toml)
error: Unexpected argument type. Expected: "core::integer::u64", found: "core::integer::u8".
--> listings/ch02-common-programming-concepts/no_listing_05_mut_cant_change_type/src/lib.cairo:6:9
x = 5_u8;
^**^
error: could not compile `no_listing_05_mut_cant_change_type` due to previous error
error: `scarb metadata` exited with error
Artık değişkenlerin nasıl çalıştığını keşfettiğimize göre, sahip olabilecekleri daha fazla veri türüne bakalım.