0

I am trying to make a procedure that tells me the depth of a list. This is what I have so far:

(define (depth lst)
  (let recurse ((lst lst) (n 1))
    (cond ((null? lst) '())
          ((not (pair? (car lst)))
           (cons n (recurse (cdr lst) n)))
          (else
           (append (recurse (car lst) (+ 1 n))
                   (recurse (cdr lst) n))))))

This works fine, but it returns the depth as a list containing the result instead of a number. For example, when I run (depth '(((a)))), it returns (3) instead of just 3.

Alexis Dumas
  • 1,299
  • 11
  • 30

1 Answers1

1

Well, the simplest answer would be to just call car on the let form. Here is what that would look like (I've taken the liberty of reformatting your code and fixed the shadowing of the depth function):

(define (depth lst)
  (car (let recurse ((lst lst) (n 1))
         (cond ((null? lst) '())
               ((not (pair? (car lst)))
                (cons n (recurse (cdr lst) n)))
               (else
                (append (recurse (car lst) (+ 1 n))
                        (recurse (cdr lst) n))))))))

However, that would not be in the spirit of the question. In this case, the function is actually working better than you think. It is giving you the depths of the lists contained in the top-level list (including the outer list, though), so here's what interacting with it looks like in the REPL:

> (depth '((((a)))))
'(4)
> (depth '((((a))) ((b)) (c)))
'(4 3 2)

Now, this is actually really useful and interesting behavior, but if it's not what you want, you'll have to rewrite the entire function. Here's how I would write it. Note that the cond could have one less arm if I combined the first and second ones, but that's a matter of preference:

(define (depth lst)
  (cond
    [(empty? lst) 0]
    [(not (pair? lst)) 0]
    [else (+ 1 (depth (car lst)))]))

Notice that this is much, much shorter, and you can still get the same result as your original function by doing this:

(define (depth-many lst) (+ 1 (map depth lst)))

In any case, the new depth function (depth-prime?) takes an argument. If it's empty or a non-list item, it's at the bottom level, so it doesn't need to do anything anymore. Otherwise (meaning it has a list argument) it calls car on the list and itself on that car, to get the first element of it, and adds one to that result.

Hope that helps!

Alexis Dumas
  • 1,299
  • 11
  • 30
  • How on earth did you make it so simple????????? This is mind blowing. Thanks again! –  Nov 02 '17 at 01:33
  • The difference was that your function was including all of the logic to do both in-place depth-finding and the depth-finding over whole the list, all in one place, effectively reimplementing `map` in the process. If I reimplemented `map` and put all of the code in one place, it might have actually been *more* complicated than yours. The key is to never reimplement when you don't have to, and break things up into smaller, more abstract pieces. I recommend keeping https://docs.racket-lang.org/reference/pairs.html open while you write. – Alexis Dumas Nov 02 '17 at 01:39