Regarding your question : "Is there a way to avoid this line: Some(ret) =>
{return
Some(ret);},"
You could do :
****************************************
fn match_fn<'a>(&'a self, filter: &'a |&'a UINode| -> Option<uint>)
->Option<uint> {
let mut result: Option<uint> = None;
for inside in self.list.iter() {
match (*filter)(*inside) {
Some(found) => {result = Some(found); break;},
None => {},
};
//try on sub tree
match **inside {
DrawableNode(_) => {},
ContainerNode(ref list_inside) => {
match list_inside.match_fn(filter) {
Some(ret) => {result = Some(ret); break;}
None => {}
}
},
}
}
result
}
****************************************
The "break" ensures that as soon as a result is found, the for loop is exited.
On Mon, Apr 28, 2014 at 7:25 PM, Philippe Delrieu
<[email protected]>wrote:
> Hello,
>
> I've updated my sample code to reflect what I'll do in my main program. I
> put it back on the list because it can help as a pattern to manage a tree
> of polymorph object.
> It compile and works.
> I have some question too because I'm not sure I've done it the right way:
> * I cross the tree recursively and return Option in each call. To
> manage recursion I put the call in a match and end with this sort of
> boilerplate code:
> match obj.call_fn_recusive() {
> Some(ret) => {return Some(ret);},
> None => {},
> }
> Is there a way to avoid this line: Some(ret) => {return
> Some(ret);},
> * It's very hard to manage reference and borrowing of object. I spend
> some time to make it compile and change my algorithm several time. That's
> why I think examples and patterns can be very useful because you can't do
> what you want in rust. In other works there is no easy shortcut, you have
> to find the right way.
> * closure indentation. Is there a good way to indent closure in function
> call to make it readable easily. It's very hard to find the begin/end of
> the closure code from the function and match call (see code).
>
> Some world about the pattern :
> I use an enum to define a type that manage all my polymorph object (enum
> UINode). It's the simplest way I found to have a collection a different
> objects that implement part of the same trait. I don't want to use unsafe
> code and low memory management. Perhaps there is a better pattern.
> The object can only be retrieve or modified with search function that use
> a closure to do the job. It's work well to avoid to know how the tree is
> organized and to avoid object reference outside the tree. The mutable part
> is restricted to one function too.
>
> The code:
>
> use std::vec::Vec;
>
> pub enum UINode {
> DrawableNode(Inside),
> ContainerNode(ListInside),
> }
>
> //common trait for all object
> trait Component {
> fn get_width(&self) -> uint;
> fn get_id(&self) -> uint;
> }
>
> //first struct. derive clone because it can be return as a copy.
> //base component.
> #[deriving(Clone)]
> pub struct Inside {
> id: uint,
> width: uint,
> }
>
> impl Component for Inside{
> fn get_id(&self) -> uint {self.id}
> fn get_width(&self) -> uint {
> self.width
> }
> }
>
> //the container that is a component and a container of components.
> pub struct ListInside {
> id: uint,
> width: uint,
> list: Vec<~UINode>,
> }
>
>
> impl Component for ListInside{
> fn get_id(&self) -> uint {self.id}
> fn get_width(&self) -> uint {
> self.width
> }
> }
>
> //some container function and the search and modify function.
> impl ListInside {
> fn addInside(&mut self, inside: Inside) {
> self.list.push(~DrawableNode(inside));
> }
>
> fn addList(&mut self, list: ListInside) {
> self.list.push(~ContainerNode(list));
> }
>
> // search for a UINode using the closure filter to find the right.
> Return the node Id.
> fn match_fn<'a>(&'a self, filter: &'a |&'a UINode| -> Option<uint>)
> ->Option<uint> {
>
> for inside in self.list.iter() {
> match (*filter)(*inside) {
> Some(found) => return Some(found),
> None => {},
> };
> //try on sub tree
> match **inside {
> DrawableNode(_) => {},
> ContainerNode(ref list_inside) => {
> match list_inside.match_fn(filter) {
> Some(ret) => {return Some(ret);}
> None => {}
> }
> },
> }
> }
> None
> }
>
> //modify using the specified closure the Component with specified id.
> fn test_mutable<'a>(&'a mut self, id: uint, update: &'a|&'a mut
> Inside|) {
> for node in self.list.mut_iter() {
> match **node {
> DrawableNode(ref mut inside) => {if inside.get_id() == id
> {(*update)(inside)}},
> ContainerNode(ref mut list_inside) =>
> list_inside.test_mutable(id, update),
> }
> }
> }
>
> //return a copy of the Component with specified id. Doesn't return
> container, only Inside.
> fn search_node<'a>(&'a self, id: uint) -> Option<~Component> {
> for node in self.list.iter() {
> match **node {
> DrawableNode(ref inside) => if inside.get_id() == id {
> return Some((~inside.clone()) as ~Component);},
> ContainerNode(ref list_inside) => { match
> list_inside.search_node(id) {
> Some(elem) => {return Some(elem);},
> None => {},
> }},
> }
> }
> None
> }
> }
>
> fn TestTreeSearchModify() {
> let mut list_inside = ListInside{
> id: 0,
> width: 10,
> list: Vec::new(),
> };
>
> let mut list2 = ListInside{
> id: 3,
> width: 30,
> list: Vec::new(),
> };
>
> let inside1 = Inside {
> id: 1,
> width: 21,
> };
>
> let inside2 = Inside {
> id: 2,
> width: 22,
> };
>
> list_inside.addInside(inside1);
> list2.addInside(inside2);
> list_inside.addList(list2);
>
> let search_id = 2;
> let new_width:uint = 122u;
>
> match list_inside.match_fn(&|inside: &UINode| -> Option<uint> {
> println!("Inside match closure node:{:?}", inside);
> match *inside { //search for id 2;
> DrawableNode(ref inside) => if inside.get_id() == search_id {
> return Some(inside.get_id());},
> ContainerNode(ref list_inside) => if list_inside.get_id() ==
> search_id { return Some(list_inside.get_id());},
> }
> None
>
> }) {
> Some(found_id) => {
> match list_inside.search_node(found_id) {
> Some(compo) => println!("Found component with id {0} and
> width {1}", compo.get_id(), compo.get_width()),
> None => {println!("Search_node deosn't work first");}
> };
> list_inside.test_mutable(found_id, &|component: &mut Inside| {
> component.width = new_width;
> });
> match list_inside.search_node(found_id) {
> Some(compo) => println!("Found updated component with id
> {0} and width {1}", compo.get_id(), compo.get_width()),
> None => {println!("Search_node deosn't work bis");}
> };
> },
> None => {println!("Match_fn deosn't work first");},
>
> }
> }
>
> #[main]
> fn main() {
> TestMatchBorrow();
> }
>
>
> Philippe
>
> _______________________________________________
> 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