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