Ok, so we all know about foldr and how it works on lists. But what about a foldr that works on nested lists? This is the problem that I'm tackling today, building a function called nested-foldr that takes in the same parameters as foldr but works with nested lists as well.
Since the nested lists can have as many lists inside them, here is an example
(nested-foldr + 0 (list 1 (list 5 5 (list 1 3)) (list 10 2) 2))
This should return 29.
I haven't gotten much down yet. I made a function called my-foldr, which basically does what foldr does. "combine" is the function that is applied to the list, "base" is the base case. "lst" is the list that the function consumes.
(define (my-foldr combine base lst)
(cond [(empty? lst) base]
[else (combine (first lst) (my-foldr combine base (rest lst)))]))
Edit: I've thought a bit more about it and the use of the "member?
" predicate should be useful here too. Though I am not sure how I can use it.
Your solution isn't taking into consideration that any element in the list can be a list itself, and we need to recur over it - in fact, we're dealing with trees, not just lists. It's trickier than it seems, and I can't think of a way to preserve foldr
order without first reversing the input. Nevertheless, this worked for me:
(define (reverse-tree tree)
(let loop ((lst tree)
(acc '()))
(cond ((null? lst) acc)
((not (pair? lst)) lst)
(else (loop (cdr lst)
(cons (car lst)
acc))))))
(define (nested-foldr combine base tree)
(let loop ((lst (reverse-tree tree))
(acc base))
(cond ((null? lst) acc)
((not (pair? lst)) lst)
(else (loop (cdr lst)
(combine (nested-foldr combine base (car lst))
acc))))))
For example:
(nested-foldr + 0 '(1 (5 5 (1 3)) (10 2) 2))
=> 29
(nested-foldr cons '() '(1 (5 5 (1 3)) (10 2) 2))
=> '(1 (5 5 (1 3)) (10 2) 2)