Dropping the return type in a single line closure

I was using Vec<usize>::for_each to remove each matching element from a HashMap<usize, _>. Since Hashmap::remove returns Option<_> for_each is unhappy with the return type of the closure, but I can't include a semi colon without a block so I either have to have a block or call drop. (In my use case I don't care whether the keys being removed exist)

Option 1:

vec.iter().for_each(|key| { hash_map.remove(key); });

Option 2:

vec.iter().for_each(|key| drop(hash_map.remove(key));

I know that both of these approaches work, but I'm curious about what people consider more idiomatic and whether there's any subtle differences I'm missing between the implementations, or whether there's another approach that I've missed. RustFMT will turn option 1 into three lines, which feels like unnecessary noise, but calling drop here feels like a strange distraction if future me needs to change this code.

X/Y Problem disclosure: I found HashMap::retain which is probably a better fit for this problem (changing the Vec to a HashSet to remove the cost of multiple calls to Vec::contains), but am still interested in the general question about closure return types.

Option 2 is missing a closing paren, which makes it slightly longer when both options are one-liners. Still, I tend to use drop just because of the formatting treatment. You get used to it. :slight_smile:

Just because it's fun, here's another way of writing it:

vec.iter().map(|key| hash_map.remove(key)).for_each(drop);

Don't do it this way, it's probably the worst option that remains somewhat reasonable.

Though tbh I'd probably just write this as

for key in &vec {
    hash_map.remove(key);
}

No need to get fancy. for_each can sometimes be faster, but a slice iterator isn't one of those cases.

2 Likes

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.