As in the declaration, lifetime parameters are template parameters, so
Foo<'a> should be the "default" approach. Using that syntax, references
would I guess technically be &<'a>, but we just use &'a. As for the +, that
confused me when I first saw it too - on the type level, + is dealing with
traits, and I think you'd only see that when you're giving the types
themselves lifetimes. If you see Bar: Foo+'a, Foo is a trait, and Bar is a
type that implements Foo and that exists for at least the given lifetime.
I'm not sure what's going on with your last example - changing the Shopping
struct to be
struct Shopping<'a>(Bag<'a>)
produces the lifetime error, but changing to:
struct Shopping<'a> { bag: Bag<'a> }
doesn't.. That might actually be a bug. You can report it on github!
On Fri, Oct 17, 2014 at 12:30 PM, David Henningsson <[email protected]>
wrote:
> First, big thanks to both of you, Ben and Clark, for helping out. :-)
>
> Thanks for the hint on the lifetime syntax - it's a bit hard to grasp,
> sometimes it's "Foo<'a>", sometimes it's "& 'a [Foo]", and I've seen
> examples with "Foo+'a" too. But maybe this all makes sense when I'm more
> used to the language.
>
> As for how long the pointed-to data is alive for, I think it makes sense
> to default to "the same lifetime as parent struct or enum", if the lifetime
> is not explicitly specified.
>
> Btw, for some reason this does not work:
>
> let s = InBag(Bag { price: 10, weights: &[3, 5, 7] }); /* fails with
> "borrowed value does not live long enough" and "consider using a `let`
> binding to increase its lifetime" */
>
> But the below does, and can be used as a workaround:
>
> let b = Bag { price: 10, weights: &[3, 5, 7] };
> let s = InBag(b);
>
> I'm sure there's an explanation to why, but if it can be fixed so that the
> compiler interprets the first as being equivalent to the second it would be
> nice.
>
>
> On 2014-10-17 21:01, Ben Foppa wrote:
>
> Your struct has a fixed size - a reference is a pointer. Which is why it
> requires a lifetime - how long is the pointed-to data alive for? And so you
> need to tell it - in your enum example, you need to say Bag<'a> (for some
> defined 'a). For example, Bag<'static> means the pointed-to data lives as
> long as the program.
>
> On Fri, Oct 17, 2014 at 11:50 AM, David Henningsson <[email protected]>
> wrote:
>
>> Thanks for the answer. Deref is a new one for me, looks interesting by
>> means of abstraction.
>>
>> I'm also coming from the C camp but I'm not sure how to write the code
>> that I want in rust. Yet. :-)
>>
>> E g, here's one, somewhat related, C example that I'm not sure how to do
>> in Rust:
>>
>> struct bag {
>> int price;
>> int nitems;
>> int []items;
>> };
>>
>> struct cart { /* ... */ };
>>
>> struct shopping {
>> int kind; /* 0 means bag, 1 means cart */
>> union {
>> struct bag bag;
>> struct cart cart;
>> }
>> }
>>
>> struct shopping* make_shopping_bag(int price, int nitems, int *items)
>> {
>> struct shopping* result = malloc(sizeof(shopping)+nitems*sizeof(int));
>> result.kind = 0;
>> result.bag.price = price;
>> result.bag.nitems = nitems;
>> memcpy(result.bag.items, nitems*sizeof(int));
>> }
>>
>>
>> So, the bag struct would probably look like this in Rust:
>>
>> struct Bag <'a> {
>> price: int,
>> weights: & 'a [int],
>> }
>>
>> 1) It feels like "weights: [int]" would be more like the way I want it,
>> and the declaration compiles, but i can't initialize the struct or have it
>> as a local variable because its size is now unkown. Even though a static
>> initialization like "let b = Bag { price: 10, weights: [3,5,7] }" would be
>> trivial to calculate the total size of, the compiler seems not to be able
>> to do this.
>>
>> 2) I'm not sure why this lifetime has to be explicit, should default to
>> "same lifetime as parent struct" IMO.
>>
>> 3) And when I try to do like:
>>
>> enum Shopping {
>> InBag(Bag),
>> InCart( /* ... */ ),
>> }
>>
>> I get an error: "error: wrong number of lifetime parameters: expected 1,
>> found 0". I've tried both "InBag('a Bag)" and "InBag(Bag + 'a)" but that
>> ends up with other errors instead...so no idea on what to do about that?
>>
>>
>> On 2014-10-17 18:37, Clark Gaebel wrote:
>>
>> Rust is not a replacement for java, it’s a replacement for C and C++.
>>
>> To solve little “puzzles” like this, i tend to ask myself “how would I
>> do this in C”, and then write that code in rust. Building inheritance trees
>> is generally the wrong way of approaching problems. In cases where it does
>> apply, you can still do it, but be gentle. Try not to lean on them as your
>> primary means of abstraction.
>>
>> Anyhow, on to your actual problem.
>>
>> Something which might be worth trying is implementing `Deref<Circle>`
>> and `DerefMut<Circle>` for your pancake, then having a
>> `DList<Box<Deref<Circle>>>` (or just use a normal &, if you want that).
>>
>> Then you can call all your circle traits after a quick call to
>> `.deref()`, AND your `DList` will free everything properly.
>>
>> But again, there’s probably a simpler solution that doesn’t involve
>> “inheritance” that you should consider. Maybe a DList of enums? Maybe just
>> a Vec<uint> in this case? Think about how you’d do it in C.
>>
>> Regards,
>> - Clark
>>
>>
>>
>> On Fri, Oct 17, 2014 at 4:27 AM, David Henningsson <[email protected]>
>> wrote:
>>
>>> Hmm, right. The as_* could probably useful to write a macro for.
>>>
>>> Coming from the C/Java side of things I have to figure out how this
>>> works in a bigger context, e g a DList or other structure owning objects
>>> implementing HasArea. This seems to compile, e g:
>>>
>>> impl Pancake {
>>> fn as_box_circle(&self) -> Box<Circle> { box self.circle }
>>> }
>>>
>>> fn make_pancake(dl: &mut DList<Box<HasArea>>) {
>>> let p = Pancake { circle: Circle { x: 0f64, y: 0f64, radius: 1f64
>>> }, is_tasty: true };
>>> dl.push(p.as_box_circle());
>>> }
>>>
>>> But I'd assume that make_pancake would now make a copy of the pancake's
>>> circle, rather than taking ownership of the entire pancake, right? The
>>> pancake then gets dropped at function return.
>>>
>>> In this simple example perhaps this does not make that much of a
>>> difference though, but if you imagine a C struct like:
>>>
>>> struct list {
>>> list *next;
>>> circle *data;
>>> }
>>>
>>> You can now put a pointer to a pancake as data, use it as a circle, and
>>> when you finally free the list and the data that goes with it, the
>>> entire pancake will be freed. This you cannot do in rust...or can you?
>>>
>>>
>>> On 2014-10-17 07:59, Clark Gaebel wrote:
>>> > impl Pancake {
>>> > fn as_circle(&self) -> &Circle { &self.circle }
>>> > fn as_mut_circle(&mut self) -> &mut Circle { &mut self.circle }
>>> > }
>>> >
>>> > The compiler will optimize trivial functions, except cross-crate. In
>>> > those cases, use an #[inline] annotation.
>>> >
>>> >
>>> >
>>> > On Thu, Oct 16, 2014 at 10:57 PM, David Henningsson <[email protected]
>>> > <mailto:[email protected]> <[email protected]>> wrote:
>>> >
>>> > This is probably a previously asked question, but I couldn't find
>>> > it on
>>> > Google, so...
>>> >
>>> > Let's extend the Circle example from the guide a little:
>>> >
>>> > struct Circle {
>>> > x:f64,
>>> > y:f64,
>>> > radius:f64,
>>> > }
>>> >
>>> > trait HasArea {
>>> > fn area(&self)-> f64;
>>> > }
>>> >
>>> > impl HasArea for Circle {
>>> > fn area(&self)-> f64 {
>>> > std::f64::consts::PI * (self.radius * self.radius)
>>> > }
>>> > }
>>> >
>>> > struct Pancake {
>>> > circle: Circle,
>>> > is_tasty: bool,
>>> > }
>>> >
>>> >
>>> > ...now, what is the easiest way I can implement HasArea for
>>> > Pancake? I
>>> > could do this:
>>> >
>>> > impl HasArea for Pancake {
>>> > fn area(&self) -> f64 { self.circle.area() }
>>> > }
>>> >
>>> > ...but that means a lot of boiler-plate code, especially if
>>> > HasArea has
>>> > many methods. Hopefully rust will just inline/optimise the
>>> > redirection
>>> > away in most cases to avoid the runtime cost, but is there a
>>> > smarter or
>>> > more idiomatic way of doing this?
>>> >
>>> > // David
>>> >
>>> > _______________________________________________
>>> > Rust-dev mailing list
>>> > [email protected]
>>> > https://mail.mozilla.org/listinfo/rust-dev
>>> >
>>> >
>>>
>>>
>>
>>
>> _______________________________________________
>> Rust-dev mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/rust-dev
>>
>>
>
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev