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

Reply via email to