How do I write a recursive function in Racket?
Every recursive function needs a base case that returns without recursing, and a recursive case that moves measurably closer to it. For lists, that is empty? and rest.
(define (sum-list lst)
(if (empty? lst)
0 ; base case
(+ (first lst) (sum-list (rest lst))))) ; recursive caserest always returns a shorter list, so empty? is guaranteed to be reached.
#Trace it by substitution
(sum-list '(1 2 3))
(+ 1 (sum-list '(2 3)))
(+ 1 (+ 2 (sum-list '(3))))
(+ 1 (+ 2 (+ 3 (sum-list '()))))
(+ 1 (+ 2 (+ 3 0)))
6Every step is "replace an expression with its value". Nothing off-screen can change the answer — which is why Racket is used to teach this.
#The template for list recursion
(define (process lst)
(cond
[(empty? lst) BASE-VALUE]
[else (COMBINE (first lst) (process (rest lst)))]))Fill in the two blanks and you have written length, sum, map, filter and reverse.
#Accumulator style
The version above builds up pending work on the stack. An accumulator carries the answer down instead:
(define (sum-list lst [acc 0])
(if (empty? lst)
acc
(sum-list (rest lst) (+ acc (first lst)))))This is tail recursive — the recursive call is the last thing that happens — and Racket optimises it into a loop, so it runs in constant stack space.
#When it goes wrong
Infinite recursion means the problem is not shrinking. Check that you are recursing on (rest lst) and not lst.
"expected a list" errors usually mean the base case is missing, so rest was called on '().