Giving references to functions

See this chapter on YouTube: immutable references and mutable references

Reference sangat berguna untuk function (fungsi). Aturan di Rust tentang value adalah: setiap value hanya bisa dimiliki oleh satu owner (pemilik).

Code dibawah ini tidak akan berjalan:

fn print_country(country_name: String) {
    println!("{}", country_name);
}

fn main() {
    let country = String::from("Austria");
    print_country(country); // akan mencetak "Austria"
    print_country(country); // ⚠️ Kita coba cetak sekali lagi!
}

Code di atas tidak berjalan karena country telah hangus. Begini penjelasannya:

  • Step 1: Kita membuat String bernama country. country adalah pemiliknya (owner).
  • Step 2: Kita berikan country ke fungsi print_country. print_country tidak memiliki ->, sehingga ia tidak me-return apapun. Setelah print_country selesai, String yang kita buat sekarang hangus.
  • Step 3: Kita mencoba untuk memberikan country ke print_country, akan tetapi kita sudah melakukannya sebelumnya. Sehingga kita tidak memiliki country lagi untuk diberikan ke fungsi print_country.

Kita bisa membuat print_country memberikan kembali String, namun cara ini terlihat agak aneh.

fn print_country(country_name: String) -> String {
    println!("{}", country_name);
    country_name // ini adalah kembaliannya
}

fn main() {
    let country = String::from("Austria");
    let country = print_country(country); // sekarang kita mesti menggunakan let disini untuk mengambil kembali String
    print_country(country);
}

Ini adalah hasil cetaknya:

Austria
Austria

Ada cara yang lebih baik untuk memperbaiki hal ini, yaitu dengan cara menambahkan &.

fn print_country(country_name: &String) {
    println!("{}", country_name);
}

fn main() {
    let country = String::from("Austria");
    print_country(&country); // hasil cetaknya adalah "Austria"
    print_country(&country); // Kita cetak lagi! Voila! hasilnya juga keluar
}

print_country() adalah fungsi yang mengambil reference ke String: atau dengan kata lain &String. Oleh karena itu, kita berikan ia reference ke country dengan menulis &country. Atau bisa dibilang bahwa String berkata ke print_country(), "Ini saya pinjamkan &country. Kamu bisa liat isinya, tapi tetap aku yang punya datanya".

Sekarang saatnya kita lakukan sesuatu yang serupa dengan mutable reference. Ini adalah contoh dari sebuah fungsi yang menggunakan variabel yang mutable.

fn add_hungary(country_name: &mut String) { // pertama fungsi akan mengambil mutable reference sebagai parameternya
    country_name.push_str("-Hungary"); // push_str() menambahkan &str ke String
    println!("Now it says: {}", country_name);
}

fn main() {
    let mut country = String::from("Austria");
    add_hungary(&mut country); // kita juga perlu memberikannya sebuah mutable reference.
}

Maka beginilah hasilnya Now it says: Austria-Hungary.

Maka, kesimpulannya adalah sebagai berikut:

  • fn function_name(variable: String) mengambil String dan mengambil kepemilikannya it. Jika ia tidak me-return apapun, maka variabelnya akan mati di dalam fungsinya.
  • fn function_name(variable: &String) meminjam String dan hanya bisa melihat isi dari variabel tersebut
  • fn function_name(variable: &mut String) meminjam String dan bisa merubah isinya

Ini adalah contoh yang terlihat seperti sebuah mutable reference, tapi sebenarnya berbeda.

fn main() {
    let country = String::from("Austria");  // country tidak mutable, tapi kita mendapatkan hasil print Austria-Hungary.
                                            // Bagaimana bisa?
    adds_hungary(country);
}

fn adds_hungary(mut country: String) { // Inilah sebabnya: adds_hungary mengambil String dan mendeklarasikannya sebagai mutable!
    country.push_str("-Hungary");
    println!("{}", country);
}

Kenapa hal ini bisa terjadi? Ini dikarenakan mut country bukan sebuah reference: sekarang adds_hungary yang memiliki value dari country. (Ingat, yang ia ambil adalah String, bukan &String). Di saat Anda memanggil adds_hungary, ia menjadi pemilik sepenuhnya. Sekarang country bukan lagi pemilik dari String::from("Austria"). Jadinya adds_hungary bisa mengambil country sebagai mutable, dan hal seperti ini sangatlah aman untuk dilakukan.

Masih ingat dengan permisalan tentang pegawai dan managernya yang kita ceritakan di atas? Pada case ini, ini seperti pegawai tersebut memberikan komputer miliknya, beserta akses dan juga datanya ke si manager. Si pegawai tidak lagi bisa menyentuh komputer tersebut (karena kepemilikan komputer tersebut telah berpindah), sehingga si manager bisa melakukan apa saja yang ia inginkan pada komputer tersebut.