Great, thanks for the clarifications, Niko, that helps a lot. I think I'll probably use the borrowed pointer notation.
I'm assuming that the compiler optimisation you describe works for any function returning an rvalue, not just for something that looks like a constructor (i.e. functions called "new" are not special in any way)? Thanks, Colin On 31 December 2012 03:48, Niko Matsakis <[email protected]> wrote: > You have two options. > > If you wish to use a borrowed pointer, you may write the function `new()` > like so: > > static fn new(value: &lifetime/str) -> StringReader/&lifetime { > StringReader { data: value, next: 0 } > } > > The notation StringReader/&lifetime is (probably) not well-documented. > What it means is: "a StringReader instance which contains borrowed > pointers with the lifetime `lifetime`". So basically it is specifying the > lifetime of the `value` field, in this case. Note that if the > `StringReader` had multiple borrowed pointers contained within, they would > all have to have the same lifetime. > > Alternatively, you could have the StringReader own the data it is reading > from, in which case you would want to use an `@str` or `~str`, just as you > showed. Ultimately, we would probably want both types in the standard > library, since each can be useful in different circumstances. > > Regarding your second question, the compiler makes some effort to > construct data precisely into the location where it is needed. So in the > constructor function above, what happens is that a pointer into the > caller's stack is passed as an implicit first parameter. The struct is > then written directly into the caller's stack. This works so long as the > return expression itself constructs the struct (more generally, so long as > you return an rvalue). It would not work if you stored the struct into a > variable and returned that. > > e.g., although there is no semantic difference, this program would *not* > be optimized: > > static fn new(value: &lifetime/str) -> StringReader/&lifetime { > let r = StringReader { data: value, next: 0 }; > return r; > } > > Here the compiler would produce a memcpy. > > > Niko > > > > Colin Fleming wrote: > > Hi all, > > I'm playing around with Rust a little having been interested in it for a > while. I've read the language and borrowed pointers tutorials but I'm still > struggling with what seems like a fairly trivial example. > > I have a StringReader type: > > struct StringReader { > data: &str, > mut next: uint > } > > and I'm trying to create a constructor for it: > > impl StringReader { > static fn new(value: &str) -> StringReader { > StringReader { data: value, next: 0 } > } > } > > I can't do this because the compiler "cannot infer an appropriate > lifetime", which I take to mean that it can't work out the lifetime of > 'value', probably because I shouldn't be using a borrowed pointer here. > > I tried a named lifetime, to indicate that the returned StringReader > pointer should be valid as long as the string is: > > static fn new(value: &lifetime/str) -> &lifetime/StringReader { > &StringReader { data: value, next: 0 } > } > > but that doesn't work either since the lifetime of the return value is not > the same as the lifetime of the param. > > I also tried by value: > > struct StringReader { > data: str, > mut next: uint > } > > static fn new(value: str) -> StringReader { > StringReader { data: value, next: 0 } > } > > but to my amazement "bare `str` is not a type" - I'd expected this just to > create an inefficient copying version. > > The only thing I've managed to get to work is an owned string: > > struct StringReader { > data: ~str, > mut next: uint > } > > static fn new(value: ~str) -> StringReader { > StringReader { data: value, next: 0 } > } > > Is this my best option here? What is the best practice for constructors? > > Another thing that I don't quite understand: according to the tutorials, a > struct constructed so: > > StringReader { data: value, next: 0 } > > is allocated on the stack. How does this work with the return value of the > constructor? Since the return value is only in scope in the constructor > body, I suppose this means that the return value of the constructor is > copied - isn't this inefficient for constructors? > > Thanks for any and all clarification, > Colin > > _______________________________________________ > Rust-dev mailing > [email protected]https://mail.mozilla.org/listinfo/rust-dev > >
_______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
