Short Answer:
Use pair?
instead of empty?
and switch the clauses. Giving you:
(define (depth tree)
(cond
[(pair? tree)
(+ 1 (max (depth (cadr tree))
(depth (caddr tree))))]
[else 0]))
Long Answer
The problem is your use of cadr
and caddr
, as you can see when you run your given example:
The actual error being:
cadr: contract violation
expected: (cons/c any/c pair?)
given: 2
This is because you're only checking empty?
, which returns #t
only when given an empty list. A number like 2
is NOT an empty list, so it returns #f, and it moves onto the second case, where you try to take the cadr of an empty list. Obviously this is going to fail.
Checking to see if something is a pair?
gets you the actual case you want.
In general, you'll be much better off taking a step back and actually thinking of the datatype of what you are traversing over.
For example, I could write out:
Tree = (Cons LeftNode RightNode)
| Number
With that in mind its much easier to see that car
and cdr
will directly access your children.
(car (Cons LeftNode RightNode)) => LeftNode
(cdr (Cons LeftNode RightNode)) => RightNode
And obviously car
and cdr
of a number is going to be an error.
From here its fairly obvious how to define your depth function
(define (depth tree)
(cond
[(pair? tree)
(+ 1 (max (depth (car tree))
(depth (cdr tree))))]
[else 0]))
Note here that I used pair?
instead of empty?
. If you really want to understand what's going on here I highly recommend you check out How To Design Programs, which takes you through the design recipe steps I'm using here in a much slower (and cleaner) way.
If you want you can even extend this idea to contain trees with 3 or 4 child nodes:
Tree = (Listof Tree Tree Tree)
| (Listof Tree Tree Tree Tree)
| Number
Given this, can you figure out a rough datatype for a tree with an arbitrary amount of sub-tree nodes?