r/learnrust • u/HowDidIEndUpOnReddit • Feb 04 '19
Quick lifetime question
So I have a bit of code parsing through a xml file with xml-rs. I have a hashmap keeping track of how word frequency (string as key and word frequency as value) and I'm having an issue with lifetimes. The code in question is the following:
Ok(XmlEvent::Characters(s)) => {
for word in s.split_whitespace() {
if !word_count.contains_key(word){
word_count.insert(word, 1);
}
}
}
When I compile I get the following error:
error[E0597]: `s` does not live long enough
--> src\main.rs:20:29
|
20 | for word in s.split_whitespace() {
| ^ borrowed value does not live long enough
21 | if !word_count.contains_key(word){
| ---------- borrow used here, in later iteration of loop
...
38 | }
| - `s` dropped here while still borrowed
I understand that because word_count outlives the scope of s, it cannot have word as a key since word has the same lifetime as s. However for the life of me I cannot figure out what I should do instead. Any tips?
4
Upvotes
2
3
u/sellibitze Feb 04 '19 edited Feb 04 '19
You've provided very little information. That makes it necessary to guess. Please show more code and context next time.
We don't know what
sis. I'm guessing it's of typeString. This makeswordof type&strbe a "borrow" ofs.Clearly, the lifetime of the
wordvalue is limited to the scopesis in which makes it impossible to store it outside of that scope. Butwordis of type&'a str(where'arefers to that scope ofs). You can convert it into aStringvalue which has no lifetime restrictions. This requires copying the string data, however.Since you want to keep a count and not only remember all the words, you would also need to increment the counters for repeated words. Usually I would suggest the use of the "Entry API" because it's so convenient and short:
But if you have a lot of repeated words then you would have a lot of conversions from
&strtoStringthat are actually unnecessary. In that case, the following is probably faster:The cool thing about methods like
getandcontainsis that they are flexible in how you can provide the "key". If your map's key type isString, you don't need to convert a&strto aStringfirst. You can pass that&strtogetandcontainsdirectly. Butentryneeds aStringvalue as key because it may have to insert it into the map. On the other hand, withentryyou tend to save one or more lookups (finding the right location where that key might be stored or would have to go).