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,¬left,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.