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
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
[rust-dev] How to end a task blocked doing IO
Hello! I'm writing my first non trivial program in Rust and I'm facing now a blocking issue (pun intended): I have to read/write data from/to a TcpStream, so I create a task for reading and a task for writing. fn do_tcp_stuff(sck : TcpStream) { let mut wtr = ~BufferedWriter::new(sck.clone()); let mut rdr = ~BufferedReader::new(sck); let (inport, inchan) = Chan::new(); let (outport, outchan) = Chan::new(); spawn(proc() { do_tcp_write(wtr, outport); }); spawn(proc() { do_tcp_read(rdr, inchan); }); loop { // do interesting things, select!() and such } } fn do_tcp_write(mut wtr : ~Writer, port : Port~[u8]) - IoResult() { loop { let data = port.recv(); try!(wtr.write(data)); wtr.flush(); } Ok(()) } fn do_tcp_read(mut rdr : ~Reader, chan : Chan~[u8]) - IoResult() { loop { let block = try!(rdr.read_bytes(1024)); chan.send(block); } Ok(()) } And all works perfectly... until I want to close the connection and kill the tasks: - The do_tcp_write() function is blocked in port.recv(), so if I close the outchan it will finish automatically. Nice! - But the do_tcp_read() function is blocked in rdr.read_bytes() so closing inport will not affect it, unless it happens to receive some data. I've read that in older iterations of the library I could use linked tasks or something like that. But in master that seems to have disappeared. I tried also closing the connection, but I couldn't find how. Is there any way to do what I want? Or am I doing something fundamentally wrong? Thank you in advance for your help! -- Rodrigo ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev