I'm trying to get some code that looks something like this to work:
struct Item {
document: String,
appender_string: String,
doc_vec: Vec<String>
}
impl Item {
pub fn new(doc: String, app: String) -> Item {
Item{document: doc, appender_string: app, doc_vec: Vec::new()}
}
pub fn load_doc(&mut self) {
for line in self.document.lines() {
self.append(line);
}
}
fn append(&mut self, line: &str){
let mut l = line.to_string();
l.push_str(&*self.appender_string);
self.doc_vec.push(l);
}
}
fn main() {
let mut i = Item::new("test\nthis\nthing\n".to_string(), "!".to_string());
i.load_doc();
println!("{:?}", i.doc_vec);
}
Which gives me the following error:
<anon>:14:13: 14:17 error: cannot borrow `*self` as mutable because `self.document` is also borrowed as immutable
<anon>:14 self.append(line);
^~~~
<anon>:13:21: 13:34 note: previous borrow of `self.document` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `self.document` until the borrow ends
<anon>:13 for line in self.document.lines() {
^~~~~~~~~~~~~
<anon>:16:6: 16:6 note: previous borrow ends here
<anon>:13 for line in self.document.lines() {
<anon>:14 self.append(line);
<anon>:15 }
<anon>:16 }
^
error: aborting due to previous error
playpen: application terminated with error code 101
I understand the issue here, you can't borrow the different fields in self
independently, but I was hoping to structure my code something like this. Is there a good way of doing what I'm describing? The key in this example is that both document
and doc_vec
should be owned by the Item
struct.
Frustratingly, this works just fine:
struct Item {
document: String,
appender_string: String,
doc_vec: Vec<String>
}
impl Item {
pub fn new(doc: String, app: String) -> Item {
Item{document: doc, appender_string: app, doc_vec: Vec::new()}
}
pub fn load_doc(&mut self) {
for line in self.document.lines() {
let mut l = line.to_string();
l.push_str(&*self.appender_string);
self.doc_vec.push(l);
}
}
}
fn main() {
let mut i = Item::new("test\nthis\nthing\n".to_string(), "!".to_string());
i.load_doc();
println!("{:?}", i.doc_vec);
}
But in the real-world case I'm trying to work with both append
and load_doc
are much longer functions, which would make this solution unwieldy. Is there a way I can get this to work as two separate functions?
Besides this specific case I frequently find that I have to compromise abstraction to get lifetimes and/or borrowing to come together properly, does anyone have any good general advice for this?