Reading the rust tutorial managed and owned pointers can be passed to a function requiring borrowed pointers as-is and are converted to borrowed pointers at compile time.
Why can't the stack variable be passed in the same way? What syntax or feature requires the explicit &
operator to pass that one as opposed to the compiler automatically converting it?
struct Point {x: float, y: float}
let on_the_stack : Point = Point {x: 3.0, y: 4.0};
let managed_box : @Point = @Point {x: 5.0, y: 1.0};
let owned_box : ~Point = ~Point {x: 7.0, y: 9.0};
fn compute_distance(p1: &Point, p2: &Point) -> float {
let x_d = p1.x - p2.x;
let y_d = p1.y - p2.y;
sqrt(x_d * x_d + y_d * y_d)
}
compute_distance(&on_the_stack, managed_box);
compute_distance(managed_box, owned_box);
Adding to the confusion is a quote from kibwen on ycombinator (I can't find the original quote but here's the quote of the quote)
We’ll still have & and &mut, but those aren’t pointers, they’re references (it’s our own fault for calling them “borrowed pointers” in our documentation)
If compute_distance
is taking references and the compiler converts pointers to references automatically why can't it do the same for values?
Edit: Since pnkfelix seems to know what he's talking about I'll copy some dialogue here for easier reading.
pnkfelix
The designers of Rust decided to not follow the path of C++ in this respect. One side-effect of this decision is that when someone reading the code looks at an invocation like f(x, y) in Rust, one need not spend time wondering "wait, how does f take its arguments; if it mutates y, will I see that reflected in that after f returns? What about x?" etc.
J V
I may be confused on the nature of references then.
@var
and~var
in rust are pointers (Though they do behave more like references) - are C++ references simply pointers under the hood?In any case, I could apply the same logic to C with regards to code readability.
Variables are either values or pointers (Where you simply pass the variable as you do in rust:
f(var)
) or are referenced in the function call (like you do in rust:f(&var)
) - I would have thought the rust compiler would recognize the function signature and handle this automatically. I don't see the improvement over C or C++
pnkfelix
One followup: this line that I wrote: "wait, how does f take its arguments; if it mutates y, will I see that reflected in that after f returns? What about x?" is somewhat facetious, since even a call like f(&x, y) would not be able to modify x; it would have to be f(&mut x, y). (and the declaration of x itself would have to be let mut x = ..., etc. – pnkfelix 1 hour ago
2nd followup: a reason why explicit &x may be more important in Rust than in C/C++ (rather than letting f(x,y) implicitly do the borrow &x), is because the borrow checker forces borrows to follow certain rules, and will refuse to compile code that does not conform. When you get an error from the borrow-checker, IMO it is a better user-experience if the compiler points to an expression of the form &x or &mut x in the source, rather that pointing to a function call and saying "there's an implicit borrow here." (That's subjective opinion, of course.) – pnkfelix 1 hour ago
I saw that you had a follow-up note in your reply, but I don't understand the point you are making about applying "the same logic to C". If you mean C as opposed to C++, then you usually do have to explicitly take addresses of memory when invoking functions that expect pointers. If a function takes a
int**
, then someone needs to do&E
whereE
is an l-value of typeint*
. That seems analogous to Rust to me. (The main exception to this that I recall offhand from C is function-pointers; you don't need to do&f
to make a function pointer tof
.) – pnkfelix 1 hour ago
J V
That seems analogous to Rust to me. - exactly my point - from a readability point of view there's not much of an improvement over plain C. because the borrow checker forces borrows to follow certain rules...rather that pointing to a function call and saying "there's an implicit borrow here." Bingo - this is one of the underlying reasons I was looking for. If you find any other reasons for the manual cast feel free to add to your answer!