Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use ref in Rust?

Tags:

rust

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?

like image 362
chenzhongpu Avatar asked Jun 21 '21 06:06

chenzhongpu


People also ask

What does REF mean in Rust?

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.

How do you use references in Rust?

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.

What is borrow checker in Rust?

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.

What is a mutable reference?

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.

What is Refref in rust?

ref - Rust Keyword ref [ −] [src] Bind by reference during pattern matching. ref annotates pattern bindings to make them borrow rather than move.

How to get the value of a referent in rust?

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.

What is the difference between C++ and rust references?

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:

How many mutable references can be created at once in rust?

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.


1 Answers

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 that Some(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 the ref 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 bind name* 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 like ref, 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 a struct 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

like image 110
Peter Hall Avatar answered Oct 21 '22 21:10

Peter Hall