What the use of copied() in Option enum?

fn main() {
    use std::collections::HashMap;

    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    let team_name = String::from("Blue");
    let score = scores.get(&team_name).copied().unwrap_or(0);
}

Here , im trying to get a value out of hashmap and, I know its converting the reference value into a owned value by using the copying, but what the use of that, cant i use the reference itself. Got this code from hashmap section of rust book.

You can, but with primitive types like integers, it's sometimes more convenient to have the value itself.

1 Like

Do u know any exact reason, why its using only for primitive types?

I don't understand your question. .copied() can be used for any Copy type, not just primitives.

No we can't use copied() , if the values lies in the hashmap is String type, for example..

    scores.insert(String::from("Blue"), String::from("Blue"));
    scores.insert(String::from("Yellow"), String::from("Blue"));

    let team_name = String::from("Blue");
    let score = scores.get(&team_name).copied().unwrap_or(0);```

The equivalent for types that are Clone but not Copy is .cloned() but of course you should only use it when you actually need the copies.

1 Like

Yes, you said it. But again whats the use case of copied() or cloned() function for Option enum. Its actually converting the Option<&T> into an Option< T > . Why here in this example they are doing this?

They’re mostly glue methods for convenience. Sometimes you have to pass an Option<T> to somewhere and all you have is an Option<&T>.

3 Likes

I believe because they want score to be an integer, not a reference to an integer.

2 Likes

Thats a good possibility!

Here, the combination foo.copied().unwrap_or(0) is just a way to save the effort of writing

match foo {
    Some(reference) => *reference,
    None => 0,
}

Why dereference (and thus copy) in the Some branch? The types must match! reference is a &i32, whereas 0 is a i32.

Why not make the 0 a reference instead? In fact in this case it does work

match foo {
    Some(reference) => reference,
    None => &0,
}

or

foo.unwrap_or(&9)

However, this relies on static promotion of the &0 to be usable, and the additional reference indirection sort-of feels “unnecessary” anyways. The static promotion would break down, as soon as the fallback value would be runtime-generated, too:

let score = scores.get(&team_name).copied().unwrap_or(&generate_fallback());
use(score);

^^^ this would result in lifetime errors. These in turn could be avoided by storing the generated fallback in some local variable, but at that time it becomes tedious. And as soon as you do this in a context where you may want to return the i32 (or &i32) from the containing function, using references may no longer work at all, if the fallback value was generated inside the function, and thus owned by it. (If you own it inside of the function, you cannot return a reference to it.) I’m skipping the effort of proactively writing code examples for everything I’ve said in this paragraph, but feel free to ask for some as a follow-up, for any point you cannot imagine yourself based on my description alone.

1 Like

I said all Copy types. String is not Copy.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.