Rust dilindeki "ownership", "borrowing", "slicing"

Rust dilindeki "ownership", "borrowing", "slicing" kavramlarına örnekler verdim ve özetmeleye çalıştım.

fn main() {
{/* ownershipRust programlama dilinin değişken kuralları.   Her değerin değişkenine yani değer tutucusuna "owner" denir.   Her seferinde değeri sadece bir "owner" tutabilir.   "owner" süslü parantezler arasından çıkarsa değer silinir.Rust bu şekilde olabildiğince gereksiz kopyalamayı azaltır.Böylece hem hız artar hem hafıza kullanımı azalır.*/
let s = "hello";{    let s="world"; // değişken oluştu ve prantezden çıkınca silindi.}println!("{}",s);
/*    Hep bahsedilir Stack ve Heap.    - Stack LIFO prensibiyle fon giren ilk çıkar şeklinde çalışan bir yazı türüdür. Değerin boyutu bellidir. Düzenlidir. Direk erişim sağlanır.    arantezlerden çıktığında silinir.    - Heap yığma bir dağ gibidir. Düzen yoktur. İşaretçilerle erişim sağlanır. Parantezlerden çıktığında silinmez.    İşaretçiler önce adresi bulur sonra değer bulununca işlem gerçekleşir. Bu yüzden işlem hızı yavaştır.    Silinmeyince hafızada açık oluşur. Tüm sorun buradadır. Otomatik silinmesi için RAII kullanılır fakat c++ olduğu gibi değilde rust bu işi otomatik sağlar.    Silme işlemini yapan fonksiyon droptur. Rust otomatik bu fonksiyonu çağırır.
*/// let s = String::from("hello"); // bu değer kullanılsaydı. aşağıda değiştirilmeye çalıştığında sorun olurdu.let mut s = String::from("hello");s.push_str(", world!"); // push_str() appends a literal to a Stringprintln!("{}", s); // This will print `hello, world!`
/*    İki değişken aynı anda bir değere referans gösteriliyor. hmm sorun var. İki referans bir veriyi kontrol edemez.    İki seçenek var.    1) s1 referansı silinecek ve s2 referansı üstlenecek. Heap verilerinde yapılan yöntemdir.    2) referansda kopyalanacak. iki pointer ve iki veri olacak. Veri miktarı büyükse pahalıya mal olur.
*/let s1= String::from("referans"); // referans, heaplet s2 = s1; // referans taşımaya çalışıyor. iki değeri de istiyorsak ne yapacağız? hmmmm.//println!("s1 = {}, s2 = {}", s1, s2); // hata. s1 zaten taşındı ve s1 silindi.
let s1 = String::from("hello");let s2 = s1.clone(); // özellikle heap nesnesini kopyalamış olduk. Veri miktarı büyükse pahalıya mal olur.println!("s1 = {}, s2 = {}", s1, s2);
// Stack nesneleri için değer taşınmak yerine kopyalanır. Değerin boyutu bellidir. Pahalıya mal olmaz.let x = 5;let y = x;println!("x = {}, y = {}", x, y);
// fonksiyonel programlama dili olduğundan içinde tanımlamakta sorun yok.fn takes_ownership(some_string: String) { // some_string fonksiyon alanına girer.    println!("{}", some_string);} // some_string silinir ve `drop` fonksiyonu çalışır. Yedekleme belleği serbest bırakılır.
fn makes_copy(some_integer: i32) { // some_string fonksiyon alanına girer.    println!("{}", some_integer);} // some_integer fonksiyon alanından çıkar. Başka birşey yok.
let s = String::from("hello"); // s fonksiyon alanına girer.takes_ownership(s); // s artık fonksiyon içindedir ve buradan daha da ulaşım sağlanamaz. ...// ... fonksiyon bittiğinde s silinir.let x = 5; // x fonksiyon alanına girer.makes_copy(x); // x fonksiyonun içine taşınır, fakat i32 stack olduğundan kopyası fonksiyon içindedir. ...//... x silinmez ve fonksiyon dışından ulaşılabilir.


/*"return" değimi yerine hiçbirşey koymaz iseniz değeri geri verir.fonksiyonun hangi tipi geri vereceğini belirtmek lazım.*/fn gives_ownership() -> String {    let some_string = String::from("hello");    some_string // "return" geri dönüş değeri. başka özel birşey yok.}fn takes_and_gives_back(a_string: String) -> String {    a_string // "return" geri dönüş değeri. başka özel birşey yok.}let s1 = gives_ownership(); // return değeri "s1" e gider.let s2 = String::from("hello");let s3 = takes_and_gives_back(s2); // s2 içine hareket eder. s3 değerine geri verir.
fn calculate_length(s: String) -> (String, usize) {    let length = s.len();    (s, length) // birden fazla değer dönebilir.}let s1 = String::from("hello"); // heap nesnesilet (s2, len) = calculate_length(s1); // birden fazla değer alabilir.println!("The length of '{}' is {}.", s2, len);
}
{/* borrowing    İşte fonksiyon heap nesnelerin dışından tanınması için "ownership" kavramının yanına    "borrowing" gelmiştir.*/
fn calculate_length2(s: &String) -> usize {    s.len()}let s1 = String::from("hello"); // heap nesnesilet len = calculate_length2(&s1); // heap nesnesini ödünç alır.println!("Barrowing The length of '{}' is {}.", s1, len); // ödünç aldığından burada kullanılabilir.
/*    Eğer parametre fonksiyon içinde değiştirilecekse "&mut <veri türü>" olarak tanımlanmalıdır.    Yine verinin "mut" ile tanımlanmış olmalıdır ve fonksiyon içine mut ile girmelidir.*/fn change(some_string: &mut String) {    some_string.push_str(", world"); // &mut String değilse değişiklik yapılamaz.}let mut s = String::from("hello"); // mut değilse değişiklik yapılamaz.change(&mut s); // mut değilse değişiklik yapılamaz.
/*    Aynı anda iki tane "&mut" referans olamaz. Derlenebilir ama olamaz.*//*let mut s = String::from("hello");let r1 = &mut s;let r2 = &mut s; // ikince referansprintln!("r1={}, r2={}", r1, r2);*/let mut s = String::from("hello");{    let r1 = &mut s;
} // r1 çıkış silinir ve sorun kalmaz.let r2 = &mut s;// println!("r1={}, r2={}", r1, r2); //r2 silindi.println!("r2={}", r2);
// istediğin kadar "immutable" referans kullanılabilir fakat immutable referanslar varken// aynı kapsamda "mutable" referans kullanılamaz.let r1 = &s; // Sorun yok.let r2 = &s; // Sorun yok.// let r3 = &mut s; // BÜYÜK PROBLEMprintln!("r2={}", r2);
// Sorunların çözümület mut x=10; // mut değilse değişiklik yapılamaz.{    let aaa=&mut x;    *aaa +=1; // mut değilse değişiklik yapılamaz.}println!("x={}",x);

fn change3(some_string: &mut String) {    some_string.push_str(", world"); // &mut String değilse değişiklik yapılamaz.}let mut sHello = String::from("hello");
{    let s=&mut sHello;    // change(&mut s); // referansları bir daha referans olarak kullanmaya çalışmayın.    change(s);}println!("sHello={}",sHello);

/*    Önemli sorunlardan biri de "dangling referance"tır. İşe yaramaz ve hatalara sebep olur.    Rust derleme zamanında bu hataları bulur.
fn dangle() -> &String // "dangling referance" sorununa yok açar. Tehlikeli!{    let s = String::from("hello");    &s // "dangling referance" sorununa yok açar. Tehlikeli!}let reference_to_nothing = dangle();
*///sadece normal kullan fanteziye gerek yok.fn no_dangle() -> String {    let s = String::from("hello");    s // fantezi yok,}let reference_to_nothing = no_dangle(); // sorun yok.
}

{    /*"Slice" kavramı        Bir veri setini bir anda elde etmeyi kolaylaştırır.        [x..y] x dahil y dahil değil sayı üretil ve index işlemlerinde kullanılır.    */
    fn first_word(s: &String) -> &str {        //let mut word_counter=0;        let bytes = s.as_bytes();        for (i, &item) in bytes.iter().enumerate() { // enumerate kaçıncı nesne olduğunu bulmamızı sağlar.            if item == b' ' {                return &s[0..i];                //word_counter+=1;            }        }
        &s[..]    }    let mut sfw = String::from("hello world");    let word = first_word(&sfw);    sfw.clear(); // Error!    println!("s= {}",s);
    let a = [1, 2, 3, 4, 5];    let slice = &a[1..3]; // işte diğer slice işlemleri.}
}

Yorumlar

Popüler Yayınlar