making a Tree() puts it on the stack, and makes it scoped, which is neat, but 
probably not what you're looking for. What you're doing is like this in C: 
    
    
    struct Tree {
      struct Tree* left;
      struct Tree* right;
    };
    
    struct Tree make_tree(int n) {
      struct Tree ret;
      ret.left = malloc(sizeof(struct Tree));
      struct Tree notleft = make_tree(n+1);
      memcpy(ret.left,&notleft,sizeof(struct Tree));
      ...
      return ret;
    }
    void foo() {
      ...
      
      struct Tree t = make_tree(3);
    }
    

Not only is that very confusing, there's no point since you're dynamically 
allocating the memory anyway, then blitting it from off the stack. It'd be 
faster to have (in the C) make_tree return a malloc'd pointer, and initialize 
the malloc'd data directly, without making a temporary tree structure on the 
stack. Problem with that is, you made your tree root an object, not a ref 
object.
    
    
    struct Tree* make_tree() {
      ...malloc(...)...
    }
    
    void foo() {
      struct Tree t = *(make_tree()); // uh...
    }
    

In general, when working with recursive data structures, I think it's a good 
idea to make everything a pointer. The child nodes must be pointers, so you 
should have a pointer to the root of any tree, which is memory managed the same 
way as the children. Nim has a lot of support for that pretty transparently, by 
creating a type of "ref object".
    
    
    import threadpool
    from strutils import repeat
    
    type Tree = ref object
      d: int
      left, right: Tree
    
    proc toString(root: int, o: Tree): string;
    
    proc `$`(o: Tree): string =
      toString(o.d,o)
    
    proc toString(root: int, o: Tree): string =
      if o.isNil:
        return "nil"
      let tab: string = ' '.repeat(2*(root - o.d))
      result = "Tree " & $o.d & "\n"
      result.add(tab & "- left\n")
      result.add(tab & "  ")
      result.add(toString(root,o.left))
      result.add("\n")
      result.add(tab & "- right\n")
      result.add(tab & "  ")
      result.add(toString(root,o.right))
    
    proc tree(depth: int): Tree =
      if depth == 0:
        Tree(d: 0)
      else:
        Tree(d: depth, left: tree(depth-1), right: tree(depth-1))
    
    proc main() =
      let t = spawn tree(3)
      let s = ^t
      echo(s)
    
    main()
    

No weird memory copying twiddle operator needed then, and the only caveat is 
that your root node is also a pointer, rather than arbitrarily being a 
structure on the stack.

Reply via email to