#lang scheme ;;; Convert to tail-recursion: ;;; Note that sc is already present, to act as ;;; an accumulator (a 'so-far' variable) ;;; ;; draw-fires : (-> (list-of fire) scene scene) (define (draw-fires-v1 lof sc) (cond [(cons? lof) (draw-fire (first lof) (draw-fires-v1 (rest lof) sc))] [(empty? lof) sc])) ; If we instead make the recursive call the outer call, ; passing in a revised `sc` to it, this version is tail-recursive: (define (draw-fires-v1-tr lof sc) (cond [(cons? lof) (draw-fires-v1-tr (rest lof) (draw-fire (first lof) sc))] [(empty? lof) sc])) ;;;; Suppose we had a slight variant -- draw-fires where we ;;;; draw onto an *empty* scene, rather than one passed in as an arg: ;; draw-fires : (-> (list-of fire) scene) (define (draw-fires-v2 lof) (cond [(cons? lof) (draw-fire (first lof) (draw-fires-v2 (rest lof)))] [(empty? lof) (empty-scene 200 200)])) ;;;; To make this one tail-recursive, we need to add a 'scene-so-far' ;;;; accumulator. ;;;; (Hey, in this case, that's what sc was all along, in the version above!) (define (draw-fires-v2-tr lof) (draw-fires-v2-tr-help lof (empty-scene 200 200))) (define (draw-fires-v2-tr-help lof scene-so-far) (cond [(cons? lof) (draw-fires-v2-tr-help (rest lof) (draw-fire (first lof) scene-so-far))] [(empty? lof) scene-so-far])) ;;;; Compare to the analog code written in Java: ; ; ; Scene drawFires( List lof ) { ; sceneSoFar = new Scene(200,200); ; firesRemaining = lof.clone(); ; while (! firesRemaining.isEmpty()) { ; sceneSoFar = drawFire( firesRemaining.get(0), sceneSoFar ); ; firesRemaining = firesRemaining.removeAt(0); ; } ; return sceneSoFar; ; } ;