What is the difference between generative and structural recursion in Racket?
What is the difference between generative and structural recursion in Racket?
Structural recursion happens when the "sub-problems" match up exactly with the possible pieces of the data.
For example, processing a list lox. The trivial case is when lox is empty. Otherwise the first sub-problem is dealing with the (first lox), and the second sub-problem is dealing with the (rest lox). You solve each sub-problem by calling a helper function, and you combine the solutions.
(define (process-list-of-x lox)
(cond
;; trivial case
[(empty? lox) ...]
[(cons? lox)
; combine the solutions
(...
; solve the first sub-problem
(process-x (first lox)) ; data-def tells you what the first sub-problem is
...
; solve the second sub-problem
(process-list-of-x (rest lox)) ; data-def tells you what the second sub-problem is
...)]))
What's different is that structural recursion tells you what the sub-problems are, where in generative recursion the sub-problems could be anything. You often need a new idea for how to break it up. A Eureka moment specific to the problem, not the data.
(define (solve-problem prob)
(cond
;; trivial case
[(trival-problem? prob) (... prob ...)]
[else
; combine the solutions
(...
; solve the first sub-problem
(solve-problem (generate-first-sub-problem prob)) ; you have to figure this out
...
; solve the second sub-problem
(solve-problem (generate-second-sub-problem prob)) ; data-def doesn't tell you how
...)]))
Also, structural recursion guarantees that it terminates because the sub-problems come from breaking up the data. In generative recursion the sub-problems can be more complicated, so you need some other way of figuring out whether it terminates.