Yes allot of copying is avoided by default when passing arguments to a function
and with less noise.
However, as my original question in this thread indicates, it is in the body of
the function that things my get complicated (ex: when using standard containers
like dequeue of seqs).
I find the rust solution to be quite beautiful:
Argument can be passed by reference (&), by mutable reference (&mut) or by
value. In the first two cases, no copy is done and in the case of &mut, the
object passed can be modified (with all the borrowing rules about &mut). But
when the object is passed by value, there is two options:
1- If the "object" implements the Copy trait, it is copied (like all primitive
types).
2- If it does not implement the Copy trait, the object is moved, and the
compiler will forbid using it any further. ex:
let v = vec![1, 2, 3];
let mut vv : Vec<Vec<i32>> = Vec::new();
vv.push(v);
println!("{:?}", v);
# generates the following error
# error[E0382]: use of moved value: `v`
# --> src/main.rs:6:22
# |
#5 | vv.push(v);
# | - value moved here
#6 | println!("{:?}", v);
# | ^ value used here after move
# |
# = note: move occurs because `v` has type `std::vec::Vec<i32>`, which
does not implement the `Copy` trait
Which means that for "big objects", there is NEVER any copy if not explicitly
stated with a "v.clone()". This enables the compiler to do some nice
optimizations and make it easier for the developer to think about performances.
In C++, it is less elegant (you have to call std::move explicitly) and moved
objects can still be accessed. But it still an important tool for optimization.
In Nim, i don't know if there is a way to tell the compiler "hey I don't need
this values here anymore, take it instead of copying it"