Such a structure should be possible with DST (a very new feature), but I 
haven’t kept up to date enough to know how to use it properly. In your example, 
where you just embed a slice instead of having the struct itself 
dynamically-sized, try:




```

struct Bag {

  price: int,

  items: Vec<int>,

}




enum Shopping {

  InBag(Bag),

  InCart(/* … */),

}




impl Shopping {

  fn new(price: int, items: Vec<int>) -> Shopping {

    InBag(Bag {

      price: price,

      items: items,

    })

  }

}

```




If you want to avoid the vector, and associated allocation, just use a slice 
instead. It’ll require some lifetime annotations, though:





```

struct Bag<‘a> {

  price: int,

  items: &’a [int],

}




enum Shopping<‘a> {

  InBag(Bag<‘a>),

  InCart(/* … */),

}




impl<‘a> Shopping<‘a> {

  fn new(price: int, items: &’a [int]) -> Shopping<‘a> {

    InBag(Bag {

      price: price,

      items: items,

    })

  }

}

```




Regards,

  - Clark

On Fri, Oct 17, 2014 at 11:51 AM, David Henningsson <di...@ubuntu.com>
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 <di...@ubuntu.com 
>> <mailto:di...@ubuntu.com>> 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
>>     <di...@ubuntu.com
>>     > <mailto:di...@ubuntu.com>> 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
>>     > Rust-dev@mozilla.org
>>     > https://mail.mozilla.org/listinfo/rust-dev
>>     >
>>     >
>>
>>
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to