4

My previous question tells me that Rust cannot take reference to itself in a struct.

So my question would become: how to design a struct when I need to reference to itself?

We might take this struct as an example:

struct SplitByChars<'a> {
    seperator: &'a Seperator,
    string: String,
    chars_iter: std::str::Chars<'a>,
}

impl<'a> SplitByChars<'a> {
    fn new<S>(seperator: &'a Seperator, string: S) -> SplitByChars where S: Into<String> {
        SplitByChars {
            seperator: seperator,
            string: string.into(),
            chars_iter: self.string.chars(), // error here: I cannot use self (of course, static method)
        }
    }
}

I used chars_iter to provide an interface of iterable string splitting.

(This is just an example, so I'd like to know about a more general idea on designing the struct, not specially in this splitting case. Moreover, no std's split.)

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Adam
  • 1,684
  • 1
  • 19
  • 39

2 Answers2

1

You can’t. Rust’s iterators are not designed to be used that way. Rearrange things so that you don’t need to store the string inside the iterator. It should only have a reference.

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
  • Let's think about the design here: `let sep = Seperator::new(",:; ");` `let split_iter = sep.split(mystring);` However, if I hold the string inside the seperator, when I want to get a new split_iter2 with `let split_iter2 = sep.split(mystring2);`, then the split_iter1 will be invalidated, which will cause the `does not live long enough` error. – Adam Aug 05 '15 at 11:08
1

While a field cannot reference another field within a struct, you can usually achieve what you need by moving them. It works by having one field as data and another field as an Option containing some struct taking that data by value (and implementing some trait of your interest).

You can find the example in this answer implementing an itetaror adaptor, where the data was a HashMap and the Option contained the map's IntoIter. During the iteration once the access to the map was no longer needed, it was moved into IntoIter using std::mem::replace.

However, in your specific case there is no method in std that would create Chars iterator by consuming the String (i.e. using self as an argument). You would have to implement it yourself.

Community
  • 1
  • 1
milancio
  • 91
  • 5