First, when using an array ([i32]
) and assigning it, you are actually creating a new copy of the array. When borrowing you are referencing the original value. In your example you are only using immutable values, so functionally there is not a difference between using arrays and borrowing but if you add mutability you can demonstrate this:
let mut array = [1, 2, 3];
let mut copy = array;
copy[0] = 10;
let borrow = &mut array;
borrow[1] = 20;
foo(array);
//print original
println!("array: {:?}", array); // Prints 'array: [1, 20, 3]'
//print copy
println!("copy: {:?}", copy); // Prints 'copy: [10, 2, 3]'
Second, Rust requires that function parameters have a defined size. Because arrays passed by value could be any size, you cannot pass arrays by value without first defining the size of the array in the function definition.
fn foo(val: [i32]) { // compile-time error
}
fn bar(val: [i32; 3]) { // allowed
}
However, &[i32]
can be passed to a function because slices have a constant size. This allows you to write functions for arrays of any length rather than one specific size. Furthermore &[i32]
is a more general type. If you have [i32]
you can always create a &[i32]
, but you cannot create a [i32]
from &[i32]
without first copying the values.
fn foo(val: &[i32]) { // also allowed because &[i32] has a fixed size
// some stuff
}