Reputation: 5088
I have this little piece of snippet of code. Why does the 2nd fail to compile?
fn apply (&self, text: Text) -> Text {
// works fine
let mut data = String::new();
for c in text.data.chars() {
let c = *self.mapping.get(&c).unwrap_or(&c);
data.push(c);
}
return Text {
data,
};
// not compile
return Text {
data: text.data.chars().map(|c| self.mapping.get(&c).unwrap_or(&c)).collect(),
};
}
Upvotes: 0
Views: 2412
Reputation: 42282
The comppiler tells you exacly why (which is why reading and posting compilation errors is useful:
8 | data: text.data.chars().map(|c| self.mapping.get(&c).unwrap_or(&c)).collect()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--^
| | |
| | `c` is borrowed here
| returns a value referencing data owned by the current function
In the case where the input char
is not present in the mapping, it returns a reference to a local variable which is not allowed as... the reference would then be left dangling, something rust does not allow.
The solution is the exact same as that used in the "works fine" version: dereference the callback's result, which will Copy
the &char
to a char
, which is owned and can thus be returned with no lifetime concerns:
Text {
data: text.data.chars().map(|c| *self.mapping.get(&c).unwrap_or(&c)).collect()
}
Alternatively you could copied
the result of HashMap::get
yielding an Option<char>
, which would then be unwrap_or
'd to char
, fixing the issue for the same reasons:
Text {
data: text.data.chars().map(|c| self.mapping.get(&c).copied().unwrap_or(c)).collect()
}
Upvotes: 1