Beginner: Idiomatic way to convert Option<&u8> to Option<u8>

#1

I have a HashMap where values are Copy types (trivial types like u8).

What is the idiomatic/best way of converting Option<&X> (returned by map.get()) to Option<X>?

Contrived example:

use std::collections::HashMap;

fn main() {
    let x = get();
}

fn get() -> Option<u8> {
    let mut map = HashMap::new();
    map.insert("a", 0u8);

    map.get("a")
}

(Playground)

1 Like
#2

You can use the Option::cloned method:

map.get("a").cloned()
#3

Ah, of course! There’s always something obvious I miss. :slight_smile: Thanks!

#4

In the future, the preferred method would probably be Option::copied, but it is not stable yet.

2 Likes
#5

Thankfully it’s been merged into master, so it will be stable on the next release. Yay! (Similarly there is Iterator::copied, which does the same thing, but for iterators! This is also stabilizing in the next release!)

#6

Thank you all. Is the move to copied purely a naming thing (to convey the meaning that the value is copied and not cloned) or is there something deeper behind it?

#7

Option::copied and Iterator::copied, from Option's docs page, seems to only differ from *::cloned in that the implementation use T: Copy instead of T: Clone, which may be different in the internal implementation (With some odd design).

#8

Yes, there is a difference, copied is guaranteed to just be a simple, cheap memcpy of what’s inside, while clone could be very expensive (ex. cloning a large Vec).

1 Like
#9

The main purpose of copied is ultimately to avoid code changes that would cause expensive clones to silently creep into your program. By using copied, you ensure that any future changes to your code will require a subsequent change from copied calls to cloned calls, so the developer will be made aware of the (potentially significant) impact of exchanging a Copy type with a non-Copy-but-Clone type.

9 Likes
#10

If your type is Copy, why not use val.map(|x| *x)

2 Likes
#11

Or if you prefer this val.map(|&x| x) also works on stable, but cloned is good enough till the next release, as most Copy types auto-derive Clone, so it should be fine to use Clone.

4 Likes
#12

Yes, it’s just naming – it means that a code reviewer will think “Of course you don’t want references to a copy type” instead of “Wait, what are they cloning there? Is it a potential performance issue?”

2 Likes