Don't understand why it works

pub fn do_find(a_sequence:&str,a_str: &str)->String
{
match a_sequence.split_whitespace().find(
|&word|{word == a_str}//Here, passing &word makes sense to me but passing just word doesn't make sense as find takes its operand by ref, yet I'm allowed to pass just word and it still compiles
)
{
    Some(a_word)=>a_word.to_owned(),
    None=>"".to_owned(),
}

Basically what I don't understand is this:
If I have a function:

fn do_something(a_str: &String)
{}

I have to call this function like so:

do_something(&some_string);

But with find in the example, even though find's closure takes its arg by ref I can pass that argument by value and it still works. In my opinion this is somewhat confusing.

When you write |&word|, that is a pattern, not a type annotation. It would be like writing this:

fn do_something(&a_str: &String) {}

This is valid syntax, but probably doesn't mean what you think it does. When an ampersand is found in a pattern, that actually means to dereference the pointer.

It's just like if you want the n from the pattern &n given the value &5, then that results in n = 5 with n not being a reference.

The reason this makes sense with find is that find only provides a borrow to the closure, and since the item type is already &str, you will get &&str from find, but your pattern dereferences once, so word has type &str.

1 Like

Hi and thank you for the reply. What &a_str means in the example above? Is it a dereferencing passed pointer? Could you provide example of usage? It will be easier to understand.
Thanks

Ok, I'll try to explain another time. The &a_str part is a pattern, so the type of &a_str is &String, and hence the type of a_str is String. So it means to dereference the provided reference. In this case it wont compile because String is not Copy, but with an integer it works:

fn do_something(&an_int: &u32) {
    // can be passed directly as u32
    takes_int(an_int);
    // to pass as &u32, we need an ampersand
    takes_ref_int(&an_int);
}

fn takes_int(int: u32) {
    println!("{}", int);
}
fn takes_ref_int(int: &u32) {
    println!("{}", int);
}

Patterns and Expressions are not the same; they are "opposite" constructs.

1 Like