Re: [rust-dev] Some help needed in Vector of enum conversion
I trying to do some polymorphism with trait and object and I have some problems. At the beginning I want to store different types of object that implement the same trait (Base) in a Vec. To do this I use the enum pattern. If the enum contains only struct, I manage to iter the Vec for the different types. code: enum BaseImpl{ FirstThinkImpl(FirstThink), SecondThinkImpl(SecondThink), } What I would like to do is to have a generic method to add like addMyBaseTrait( ~Base) to add all the struct that implement Base to the vector and to have a specific method that add a specific struct addSecondStruct(~SecondStruct). The enum is changed to: enum BaseImpl{ FirstThinkImpl(~Base), SecondThinkImpl(~SecondThink), } With this enum has have problem to iter the vector. I didn't find a way to iter all the vector and return Base or ~Base: this code impl'a Iterator'a ~Base for BaseItems'a { fn next(mut self) - Option'a ~Base{ match self.iter.next() { Some(ref baseimpl) = { Some(match ***baseimpl{ FirstThinkImpl(ref first) = first, SecondThinkImpl(ref second)= 'a (*second as ~Base), }) }, None = None, } } } generate an error borrowed value does not live long enough SecondThinkImpl(ref second)= 'a (*second as ~Base), which is logic so I try not to borrow with this code: SecondThinkImpl(ref second)= second as 'a ~Base, and I have the error non-scalar cast: `~SecondThink` as `'a ~Baseno-bounds` Perhaps there is no way. I didn't find any. What I see with all my test is that a trait must be use as a reference to be stored but object reference can't be cast to a reference trait and trait can't be cast to an object. So it seems that tray is useful to pass or return parameters to method but not to store data. Philippe Le 09/04/2014 21:53, Philippe Delrieu a écrit : I find a solution by removing the ~ to Base trait. The code //(First and Second think as defined earlier) enum BaseImpl{ FirstThinkImpl(FirstThink), SecondThinkImpl(SecondThink), } struct Container{ nodeList: Vec~BaseImpl, } impl'a Container{ fn iter_base('a self) - BaseItems'a { let iter = self.nodeList.iter(); BaseItems{ iter : iter } } } struct BaseItems'a { iter : Items'a, ~BaseImpl } impl'a Iterator'a Base for BaseItems'a { fn next(mut self) - Option'a Base{ match self.iter.next() { Some(ref baseimpl) = { Some(match ***baseimpl{ FirstThinkImpl(ref first) = first as 'a Base, SecondThinkImpl(ref second)= second as 'a Base, }) }, None = None, } } } Now it compile. So I try to define a mutable iterator like the immuable and with similar code I have again the lifetime compile error : struct BaseMutItems'a { iter : MutItems'a, ~BaseImpl } impl'a Iterator'a mut Base for BaseMutItems'a { fn next(mut self) - Option'a mut Base { match self.iter.next() { Some(ref mut baseimpl) = { Some(match ***baseimpl{ FirstThinkImpl(ref mut first) = first as 'a mut Base, SecondThinkImpl(ref mut second)= second as 'a mut Base, }) }, None = None, } } } error : test_enum.rs:125:36: 125:49 error: lifetime of `baseimpl` is too short to guarantee its contents can be safely reborrowed test_enum.rs:125 FirstThinkImpl(ref mut first) = first as 'a mut Base, I can't see what's going wrong. I put all the code if someone want to test : use std::iter::Iterator; use std::slice::{Items, MutItems}; trait Base{ fn set_something(mut self); fn isSecondThink(self) - bool; } struct FirstThink{ count1: int, } impl Base for FirstThink{ fn set_something(mut self){println!(ici First count:{:?}, self.count1); self.count1+=1;} fn isSecondThink(self) - bool {false} } struct SecondThink{ count2: int, } impl Base for SecondThink{ fn set_something(mut self){println!(ici Second count:{:?}, self.count2); self.count2+=1;} fn isSecondThink(self) - bool {true} } enum BaseImpl{ FirstThinkImpl(FirstThink), SecondThinkImpl(SecondThink), } fn some_second_process(think: mut SecondThink){ think.set_something(); } struct Container{ nodeList: Vec~BaseImpl, } impl'a Container{ fn add_FirstThink(mut self, think: FirstThink){ self.nodeList.push(~FirstThinkImpl(think)); } fn add_SecondThink(mut self, think: SecondThink){ self.nodeList.push(~SecondThinkImpl(think)); } fn iter_base('a self) - BaseItems'a { let iter = self.nodeList.iter(); BaseItems{ iter : iter } } fn iter_second('a self) - SecondItems'a {
Re: [rust-dev] Some help needed in Vector of enum conversion
I find a solution by removing the ~ to Base trait. The code //(First and Second think as defined earlier) enum BaseImpl{ FirstThinkImpl(FirstThink), SecondThinkImpl(SecondThink), } struct Container{ nodeList: Vec~BaseImpl, } impl'a Container{ fn iter_base('a self) - BaseItems'a { let iter = self.nodeList.iter(); BaseItems{ iter : iter } } } struct BaseItems'a { iter : Items'a, ~BaseImpl } impl'a Iterator'a Base for BaseItems'a { fn next(mut self) - Option'a Base{ match self.iter.next() { Some(ref baseimpl) = { Some(match ***baseimpl{ FirstThinkImpl(ref first) = first as 'a Base, SecondThinkImpl(ref second)= second as 'a Base, }) }, None = None, } } } Now it compile. So I try to define a mutable iterator like the immuable and with similar code I have again the lifetime compile error : struct BaseMutItems'a { iter : MutItems'a, ~BaseImpl } impl'a Iterator'a mut Base for BaseMutItems'a { fn next(mut self) - Option'a mut Base { match self.iter.next() { Some(ref mut baseimpl) = { Some(match ***baseimpl{ FirstThinkImpl(ref mut first) = first as 'a mut Base, SecondThinkImpl(ref mut second)= second as 'a mut Base, }) }, None = None, } } } error : test_enum.rs:125:36: 125:49 error: lifetime of `baseimpl` is too short to guarantee its contents can be safely reborrowed test_enum.rs:125 FirstThinkImpl(ref mut first) = first as 'a mut Base, I can't see what's going wrong. I put all the code if someone want to test : use std::iter::Iterator; use std::slice::{Items, MutItems}; trait Base{ fn set_something(mut self); fn isSecondThink(self) - bool; } struct FirstThink{ count1: int, } impl Base for FirstThink{ fn set_something(mut self){println!(ici First count:{:?}, self.count1); self.count1+=1;} fn isSecondThink(self) - bool {false} } struct SecondThink{ count2: int, } impl Base for SecondThink{ fn set_something(mut self){println!(ici Second count:{:?}, self.count2); self.count2+=1;} fn isSecondThink(self) - bool {true} } enum BaseImpl{ FirstThinkImpl(FirstThink), SecondThinkImpl(SecondThink), } fn some_second_process(think: mut SecondThink){ think.set_something(); } struct Container{ nodeList: Vec~BaseImpl, } impl'a Container{ fn add_FirstThink(mut self, think: FirstThink){ self.nodeList.push(~FirstThinkImpl(think)); } fn add_SecondThink(mut self, think: SecondThink){ self.nodeList.push(~SecondThinkImpl(think)); } fn iter_base('a self) - BaseItems'a { let iter = self.nodeList.iter(); BaseItems{ iter : iter } } fn iter_second('a self) - SecondItems'a { let iter = self.nodeList.iter(); SecondItems{ iter : iter } } fn mut_iter_base('a mut self) - BaseMutItems'a { let iter = self.nodeList.mut_iter(); BaseMutItems{ iter : iter } } fn appli_secondthink_someprocess(mut self, fct : fn (mut SecondThink)) { for think in self.nodeList.mut_iter() { match **think { FirstThinkImpl(first) = println!(), SecondThinkImpl(ref mut second)= fct(second), } } } } struct BaseItems'a { iter : Items'a, ~BaseImpl } impl'a Iterator'a Base for BaseItems'a { fn next(mut self) - Option'a Base{ match self.iter.next() { Some(ref baseimpl) = { Some(match ***baseimpl{ FirstThinkImpl(ref first) = first as 'a Base, SecondThinkImpl(ref second)= second as 'a Base, }) }, None = None, } } } struct SecondItems'a { iter : Items'a, ~BaseImpl } impl'a Iterator'a SecondThink for SecondItems'a { fn next(mut self) - Option'a SecondThink{ match self.iter.next() { Some(ref baseimpl) = { match ***baseimpl{ FirstThinkImpl(ref first) = self.next(), SecondThinkImpl(ref second)= Some(second), } }, None = None, } } } struct BaseMutItems'a { iter : MutItems'a, ~BaseImpl } impl'a Iterator'a mut Base for BaseMutItems'a { fn next(mut self) - Option'a mut Base { match self.iter.next() { Some(ref mut baseimpl) = { Some(match ***baseimpl{ FirstThinkImpl(ref mut first) = first as 'a mut Base, SecondThinkImpl(ref mut second)= second as 'a mut Base, }) }, None = None, } } } #[main]
Re: [rust-dev] Some help needed in Vector of enum conversion
On Sun, Apr 6, 2014 at 7:50 PM, Philippe Delrieu philippe.delr...@free.fr wrote: I need some more help. The impl Iteratormut ~Base for Container declaration generate the error: error: missing lifetime specifier So I had it but I can't manage to return the next value with the specified life time. The code : impl'a Iterator'a mut ~Base for Container { /// Advance the iterator and return the next value. Return `None` when the end is reached. fn next(mut self) - Option'a mut ~Base{ if self.iter_counter == self.nodeList.len() { None } else { self.iter_counter += 1; Some('a mut match **self.nodeList.get(self.iter_counter){ FirstThinkImpl(first) = first as ~Base, SecondThinkImpl(second)= second as ~Base, }) } } } Generate these errors : test_enum.rs:58:18: 61:14 error: borrowed value does not live long enough test/test_enum.rs:58 Some('a mut match Oh, I think I may have misleaded you... You cannot implement the iterator directly in Container, because the iterator must handle the current position, while the Container just holds the values. You need a intermediate struct that implements the Iterator traits. That's what the `iter()` and ' move_iter()` functions do for vectors and other standard containers. So you'll need something along the lines of this (disclaimer: totally untested!!): struct Container { // fn iter('a self) - BaseItems'a { let iter = nodeList.iter(); BaseItems{ iter : iter } } } struct BaseItems'a { iter : Items'a, ~Base } impl'a Iterator'a mut ~Base for BaseItems'a { // } BTW, why all the double pointer in all the mut ~Base instead of just mut Base? -- Rodrigo ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Some help needed in Vector of enum conversion
Thanks for your help. I'll test ASAP. I use the counter mutable var to have a simple implantation of the iterator to make the code works. Thank for you're example to show a better way. I was thinking of a similar way but I would like to avoid the specific struct with perhaps use a recursive call. I'll think about it later. Le 07/04/2014 10:27, Rodrigo Rivas a écrit : BTW, why all the double pointer in all the mut ~Base instead of just mut Base? For your question, I have mut ~Base because i didn't find a way to convert the mut ~Base to mut Base (or ~Base to Base) without copy. I have the error error: mismatched types: expected `std::option::Option'a mut ~Baseno-bounds` but found `std::option::Optionmut ~Baseno-bounds` I try (error above), * error type `~Baseno-bounds` cannot be dereferenced. So I stop searching and try to make it works with ~Base. The callback function is modifying the Vec instance. It's a method that update all the of the Vec element after an event occurs. I have to keep the reference to the Vec instance during the call. Perhaps there's a conception problem that I'll look later to remove most of the mut call but I try this type of call to learn who Rust works. Perhaps you can help me for this part. Philippe ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Some help needed in Vector of enum conversion
I try to implement the iterator like that: struct BaseItems'a { iter : Items'a, ~BaseImpl } impl'a Iterator'a ~Base for BaseItems'a { fn next(mut self) - Option'a ~Base{ match self.iter.next() { Some(ref baseimpl) = { Some('a match ***baseimpl{ FirstThinkImpl(ref first) = *first as ~Base, SecondThinkImpl(ref second)= *second as ~Base, }) }, None = None, } } } But I have a lifetime problem. The error is : borrowed value does not live long enough and reference must be valid for the lifetime 'a as defined on the block and : cannot move out of dereference of ``-pointer SecondThinkImpl(ref second)= *second as ~Base, Another possibility: fn next(mut self) - Option'a ~Base{ match self.iter.next() { Some(ref baseimpl) = { Some(match ***baseimpl{ FirstThinkImpl(ref first) = first as 'a ~Base, SecondThinkImpl(ref second)= second as 'a ~Base, }) }, None = None, } } generate the error: non-scalar cast: `~FirstThink` as `'a ~Baseno-bounds` I try different possibility but I didn't find how to return a 'a lifetime ~Base or Base I remove the mut to simplify the test of the different lifetime possibilities. Philippe Le 07/04/2014 10:27, Rodrigo Rivas a écrit : On Sun, Apr 6, 2014 at 7:50 PM, Philippe Delrieu philippe.delr...@free.fr wrote: I need some more help. The impl Iteratormut ~Base for Container declaration generate the error: error: missing lifetime specifier So I had it but I can't manage to return the next value with the specified life time. The code : impl'a Iterator'a mut ~Base for Container { /// Advance the iterator and return the next value. Return `None` when the end is reached. fn next(mut self) - Option'a mut ~Base{ if self.iter_counter == self.nodeList.len() { None } else { self.iter_counter += 1; Some('a mut match **self.nodeList.get(self.iter_counter){ FirstThinkImpl(first) = first as ~Base, SecondThinkImpl(second)= second as ~Base, }) } } } Generate these errors : test_enum.rs:58:18: 61:14 error: borrowed value does not live long enough test/test_enum.rs:58 Some('a mut match Oh, I think I may have misleaded you... You cannot implement the iterator directly in Container, because the iterator must handle the current position, while the Container just holds the values. You need a intermediate struct that implements the Iterator traits. That's what the `iter()` and ' move_iter()` functions do for vectors and other standard containers. So you'll need something along the lines of this (disclaimer: totally untested!!): struct Container { // fn iter('a self) - BaseItems'a { let iter = nodeList.iter(); BaseItems{ iter : iter } } } struct BaseItems'a { iter : Items'a, ~Base } impl'a Iterator'a mut ~Base for BaseItems'a { // } BTW, why all the double pointer in all the mut ~Base instead of just mut Base? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Some help needed in Vector of enum conversion
I need some more help. The impl Iteratormut ~Base for Container declaration generate the error: error: missing lifetime specifier So I had it but I can't manage to return the next value with the specified life time. The code : impl'a Iterator'a mut ~Base for Container { /// Advance the iterator and return the next value. Return `None` when the end is reached. fn next(mut self) - Option'a mut ~Base{ if self.iter_counter == self.nodeList.len() { None } else { self.iter_counter += 1; Some('a mut match **self.nodeList.get(self.iter_counter){ FirstThinkImpl(first) = first as ~Base, SecondThinkImpl(second)= second as ~Base, }) } } } Generate these errors : test_enum.rs:58:18: 61:14 error: borrowed value does not live long enough test/test_enum.rs:58 Some('a mut match **self.nodeList.get(self.iter_counter){ test/test_enum.rs:59 FirstThinkImpl(first) = first as ~Base, test_enum.rs:60 SecondThinkImpl(second)= second as ~Base, test_enum.rs:61 }) test_enum.rs:53:52: 63:6 note: reference must be valid for the lifetime 'a as defined on the block at 53:51... test_enum.rs:53 fn next(mut self) - Option'a mut ~Base{ test_enum.rs:54 if self.iter_counter == self.nodeList.len() { test/test_enum.rs:55 None test_enum.rs:56 } else { test_enum.rs:57 self.iter_counter += 1; test_enum.rs:58 Some('a mut match **self.nodeList.get(self.iter_counter){ ... test_enum.rs:56:17: 62:10 note: ...but borrowed value is only valid for the expression at 56:16 test_enum.rs:56 } else { test_enum.rs:57 self.iter_counter += 1; test_enum.rs:58 Some('a mut match **self.nodeList.get(self.iter_counter){ test_enum.rs:59 FirstThinkImpl(first) = first as ~Base, test_enum.rs:60 SecondThinkImpl(second)= second as ~Base, test/test_enum.rs:61 }) ... test_enum.rs:59:17: 59:38 error: cannot move out of dereference of ``-pointer test_enum.rs:59 FirstThinkImpl(first) = first as ~Base, ^ test_enum.rs:60:17: 60:40 error: cannot move out of dereference of ``-pointer test_enum.rs:60 SecondThinkImpl(second)= second as ~Base, Le 05/04/2014 21:59, Rodrigo Rivas a écrit : On Fri, Apr 4, 2014 at 10:41 PM, Philippe Delrieu philippe.delr...@free.fr wrote: Hello, I've some problem to find a solution for something I want to do with a vector of enum. This is an example of what I want to do: trait Base{ fn set_something(mut self); } struct FirstThink; impl Base for FirstThink{ fn set_something(mut self){} } struct SecondThink; impl Base for SecondThink{ fn set_something(mut self){} } enum BaseImpl{ FirstThinkImpl(~FirstThink), SecondThinkImpl(~SecondThink), } fn some_process(list: mut Vecmut ~Base){ for think in list.mut_iter() { think.set_something(); } } struct Container{ nodeList: Vec~BaseImpl, } impl Container{ fn add_FirstThink(mut self, think: ~FirstThink){ self.nodeList.push(~FirstThinkImpl(think)); } fn add_SecondThink(mut self, think: ~SecondThink){ self.nodeList.push(~SecondThinkImpl(think)); } fn do_some_process(mut self, fct: fn(mut Vecmut ~Base)){ I didn't find a simple way to convert the Vec~BaseImpl to a mut Vecmut ~Base to do the call fct(self.nodeList); } } I use the enum pattern to have only one collection of object that impl Base but sometime I have to do specific processing depending if the Base is a FirstThink or SecondThink (not in the example). I use the match as follow match think { FirstThinkImpl(first) = do specific first, SecondThinkImpl(second)= do specific second, }); Perhaps there is a better way to do. Any suggestions would be appreciated. I think that would be better if the `fct` function take an `std::iter::Iteratormut ~Base` instead of a `Vec`. Naturally, you will not be able to modify the vector, only to iterate through it. But if `fct` is allowed to modify the vector your requirements are impossible in the first place! Then you can write a simple adaptor: impl std::iter::Iteratormut ~Base for Container { // left as an exercise to the reader ;-) } ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Some help needed in Vector of enum conversion
On Fri, Apr 4, 2014 at 10:41 PM, Philippe Delrieu philippe.delr...@free.fr wrote: Hello, I've some problem to find a solution for something I want to do with a vector of enum. This is an example of what I want to do: trait Base{ fn set_something(mut self); } struct FirstThink; impl Base for FirstThink{ fn set_something(mut self){} } struct SecondThink; impl Base for SecondThink{ fn set_something(mut self){} } enum BaseImpl{ FirstThinkImpl(~FirstThink), SecondThinkImpl(~SecondThink), } fn some_process(list: mut Vecmut ~Base){ for think in list.mut_iter() { think.set_something(); } } struct Container{ nodeList: Vec~BaseImpl, } impl Container{ fn add_FirstThink(mut self, think: ~FirstThink){ self.nodeList.push(~FirstThinkImpl(think)); } fn add_SecondThink(mut self, think: ~SecondThink){ self.nodeList.push(~SecondThinkImpl(think)); } fn do_some_process(mut self, fct: fn(mut Vecmut ~Base)){ I didn't find a simple way to convert the Vec~BaseImpl to a mut Vecmut ~Base to do the call fct(self.nodeList); } } I use the enum pattern to have only one collection of object that impl Base but sometime I have to do specific processing depending if the Base is a FirstThink or SecondThink (not in the example). I use the match as follow match think { FirstThinkImpl(first) = do specific first, SecondThinkImpl(second)= do specific second, }); Perhaps there is a better way to do. Any suggestions would be appreciated. I think that would be better if the `fct` function take an `std::iter::Iteratormut ~Base` instead of a `Vec`. Naturally, you will not be able to modify the vector, only to iterate through it. But if `fct` is allowed to modify the vector your requirements are impossible in the first place! Then you can write a simple adaptor: impl std::iter::Iteratormut ~Base for Container { // left as an exercise to the reader ;-) } -- Rodrigo ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Some help needed in Vector of enum conversion
Very good idea. The vector don't have to be modified so it'll work. Thank you for the advice. I make a try an I'll post the result. Philippe Le 05/04/2014 21:59, Rodrigo Rivas a écrit : On Fri, Apr 4, 2014 at 10:41 PM, Philippe Delrieu philippe.delr...@free.fr wrote: Hello, I've some problem to find a solution for something I want to do with a vector of enum. This is an example of what I want to do: trait Base{ fn set_something(mut self); } struct FirstThink; impl Base for FirstThink{ fn set_something(mut self){} } struct SecondThink; impl Base for SecondThink{ fn set_something(mut self){} } enum BaseImpl{ FirstThinkImpl(~FirstThink), SecondThinkImpl(~SecondThink), } fn some_process(list: mut Vecmut ~Base){ for think in list.mut_iter() { think.set_something(); } } struct Container{ nodeList: Vec~BaseImpl, } impl Container{ fn add_FirstThink(mut self, think: ~FirstThink){ self.nodeList.push(~FirstThinkImpl(think)); } fn add_SecondThink(mut self, think: ~SecondThink){ self.nodeList.push(~SecondThinkImpl(think)); } fn do_some_process(mut self, fct: fn(mut Vecmut ~Base)){ I didn't find a simple way to convert the Vec~BaseImpl to a mut Vecmut ~Base to do the call fct(self.nodeList); } } I use the enum pattern to have only one collection of object that impl Base but sometime I have to do specific processing depending if the Base is a FirstThink or SecondThink (not in the example). I use the match as follow match think { FirstThinkImpl(first) = do specific first, SecondThinkImpl(second)= do specific second, }); Perhaps there is a better way to do. Any suggestions would be appreciated. I think that would be better if the `fct` function take an `std::iter::Iteratormut ~Base` instead of a `Vec`. Naturally, you will not be able to modify the vector, only to iterate through it. But if `fct` is allowed to modify the vector your requirements are impossible in the first place! Then you can write a simple adaptor: impl std::iter::Iteratormut ~Base for Container { // left as an exercise to the reader ;-) } ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Some help needed in Vector of enum conversion
Hello, I've some problem to find a solution for something I want to do with a vector of enum. This is an example of what I want to do: trait Base{ fn set_something(mut self); } struct FirstThink; impl Base for FirstThink{ fn set_something(mut self){} } struct SecondThink; impl Base for SecondThink{ fn set_something(mut self){} } enum BaseImpl{ FirstThinkImpl(~FirstThink), SecondThinkImpl(~SecondThink), } fn some_process(list: mut Vecmut ~Base){ for think in list.mut_iter() { think.set_something(); } } struct Container{ nodeList: Vec~BaseImpl, } impl Container{ fn add_FirstThink(mut self, think: ~FirstThink){ self.nodeList.push(~FirstThinkImpl(think)); } fn add_SecondThink(mut self, think: ~SecondThink){ self.nodeList.push(~SecondThinkImpl(think)); } fn do_some_process(mut self, fct: fn(mut Vecmut ~Base)){ I didn't find a simple way to convert the Vec~BaseImpl to a mut Vecmut ~Base to do the call fct(self.nodeList); } } I use the enum pattern to have only one collection of object that impl Base but sometime I have to do specific processing depending if the Base is a FirstThink or SecondThink (not in the example). I use the match as follow match think { FirstThinkImpl(first) = do specific first, SecondThinkImpl(second)= do specific second, }); Perhaps there is a better way to do. Any suggestions would be appreciated. Philippe ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev