I noticed the code in Microsoft's Take your first steps with Rust:
fn count_letters(text: &str) -> usize {
text.chars().filter(|ref c| c.is_alphabetic()).count()
}
It is clear that the code still works well without ref
.
Why is ref
used here? And when should I use ref
? Is there any idiomatic programming practice here?
Keyword refBind by reference during pattern matching. ref annotates pattern bindings to make them borrow rather than move. It is not a part of the pattern as far as matching is concerned: it does not affect whether a value is matched, only how it is matched.
Syntax. An ampersand ( & ) is used with a variable's name while passing its reference instead of its value to a function. The function's signature should also have an ampersand with the type of argument that receives the reference.
The borrow check is Rust's "secret sauce" – it is tasked with enforcing a number of properties: That all variables are initialized before they are used. That you can't move the same value twice. That you can't move a value while it is borrowed.
A mutable type is a type whose instance data can be modified. The System. Text. StringBuilder class is an example of a mutable reference type. It contains members that can change the value of an instance of the class.
ref - Rust Keyword ref [ −] [src] Bind by reference during pattern matching. ref annotates pattern bindings to make them borrow rather than move.
And to get the value of the referent, you'd use the * operator: All the values and references created above were immutable, which is the default in Rust. If you want to change the value through a reference, create a mutable reference.
Creating and dereferencing a reference is implicit in C++: While in Rust these are explicit: Another difference is that you can reassign a reference in Rust to another object: But you can't reseat a C++ reference:
There can be only one mutable reference at a time. The code above tries to create two mutable references to the same data. If we try to compile this code, Rust will emit this error: While it may occur unexpected, it actually makes perfect sense.
To quote from the Rust Book:
In older versions of Rust,
match
would assume that you want to move what is matched. But sometimes, that’s not what you wanted. For example:let robot_name = &Some(String::from("Bors")); match robot_name { Some(name) => println!("Found a name: {}", name), None => (), } println!("robot_name is: {:?}", robot_name);
Here,
robot_name
is a&Option<String>
. Rust would then complain thatSome(name)
doesn’t match up with&Option<T>
, so you’d have to write this:let robot_name = &Some(String::from("Bors")); match robot_name { &Some(name) => println!("Found a name: {}", name), None => (), } println!("robot_name is: {:?}", robot_name);
Next, Rust would complain that name is trying to move the
String
out of the option, but because it’s a reference to an option, it’s borrowed, and so can’t be moved out of. This is where theref
keyword comes into play:let robot_name = &Some(String::from("Bors")); match robot_name { &Some(ref name) => println!("Found a name: {}", name), None => (), } println!("robot_name is: {:?}", robot_name);
The
ref
keyword is like the opposite of&
in patterns; this says “please bindname
* to be a&String
, don’t try to move it out." In other words, the&
in&Some
is matching against a reference, but ref creates a reference.ref mut
is likeref
, but for mutable references.Anyway, today’s Rust doesn’t work like this. If you try to match on something borrowed, then all of the bindings you create will attempt to borrow as well. This means that the original code works as you’d expect.
Because Rust is backwards compatible, we couldn’t remove ref and
ref mut
, and they’re sometimes useful in obscure situations, where you want to partially borrow part of astruct
as mutable and another part as immutable. But you may see them in older Rust code, so knowing what they do is still useful.
*This was a minor correction, the book says ref
instead of name
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With