Aldimhr Home Page

TIL — Evaluasi Argumen Left-to-Right di Rust

Rust Programming Language

Aldimhr • 09-03-2025 • 2 min read

Left-to-Right Argument Evaluation in Rust

Masih berhubungan dengan Ownership di Rust, masalah ini muncul ketika saya menggunakan length dari array dan array itu sendiri sebagai argument di function.

Contoh

fn quicksort(arr: &mut Vec<i32>, lo: usize, hi: usize) { ... }

fn main() {
  let mut v = vec![1,2,3,4,5];
  quicksort(&mut v, 0, v.len() - 1);
}

Function quicksort ketika dijalankan akan muncul error

error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
 --> src/lib.rs:5:26
  |
5 |     quicksort(&mut v, 0, v.len() - 1);
  |     --------- ------     ^ immutable borrow occurs here
  |     |         |
  |     |         mutable borrow occurs here
  |     mutable borrow later used by call

Masalah

Error ini berkaitan dengan konsep Ownership, dimana Mutable Borrow &mut v tidak boleh memiliki banyak reference sekaligus.

let mut a = 10;
let b = &mut a;
let c = a;       // error
let d = &mut a;  // error
let e = &a;      // error

Sama seperti function quicksort sebelumnya, Rust akan membaca argumen dari kiri ke kanan

quicksort(&mut v, 0, v.len() - 1)

Variabel v diambil di argumen pertama dari function quicksort sebagai Mutable Borrow &mut v selanjutnya v dipanggil kembali sebagai Immutable Borrow v.len()-1 di argumen ketiga.

Kenapa v.len()-1 disebut dengan Immutable Borrow padahal tidak tertulis &v.len()-1 ? karena cara kerja method call seperti .len() secara implisit meneruskan reference v ke method tersebut len(&v), atau disebut dengan “Automatic Referencing”.

Perbaikan

Ada 2 cara untuk mengatasi error argument reference.

Pertama, menggunakan varibel baru untuk menampung length dari array

fn quicksort(arr: &mut Vec<i32>, lo: usize, hi: usize) { ... }

fn main() {
  let mut v = vec![1,2,3,4,5];
  let length = v.len();  // buat variabel baru
  quicksort(&mut v, 0, length - 1);  // perbarui argument ke tiga
}

Variabel baru dibuat untuk menampung length dari array, lalu menggunakan variabel tersebut di argumen ke tiga. Error tidak muncul lagi, karena v.len dipanggil di awal sebelum v dipanggil sebagai Immutable Borrow, dan v.len di variabel length akan selesai saat variabel sudah menyimpan value di memory. Singkatnya, tidak ada yang menggunakan v lagi ketika &mut v dipanggil.

Kedua, re-ordering argument

Cara ini dilakukan dengan menggeser &mut v ke argument paling akhir untuk menghindari penggunaan banyak reference setelah Mutable Borrow didaftarkan.

fn quicksort(lo: usize, hi: usize, arr: &mut Vec<i32>) { ... }

fn main() {
  let mut v = vec![1,2,3,4,5];
  quicksort(0, v.len() - 1, &mut v);
}

https://doc.rust-lang.org/reference/expressions.html#evaluation-order-of-operands

https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html