Corecursion Doesn't Terminate After Small Change

141 views Asked by At

I wrote a function in Racket to produce something similar to the following fractal.

Circle Fractal

(define CUT-OFF 5)
(define CIRCLE-MODE "outline")

(define (circle-fractal size colour)
  (local [(define full-circle (circle size CIRCLE-MODE colour))]

    (cond [(<= size CUT-OFF) full-circle]
          [else
           (overlay/align "middle" "middle" 
                          full-circle
                          (beside (circle-fractal (/ size 2) colour)
                                  (circle-fractal (/ size 2) colour)))])))

It passes my tests.

I changed the code, thinking the below would be more readable.

(define (circle-fractal size colour)
  (local [(define full-circle (circle size CIRCLE-MODE colour))
          (define half-circle (circle-fractal (/ size 2) colour))]

    (cond [(<= size CUT-OFF) full-circle]
          [else
           (overlay/align "middle" "middle" 
                          full-circle
                          (beside half-circle half-circle))])))

Now the function doesn't terminate. Racket reaches its memory limit with no output.

Does each corecursive call somehow not approach the trivial case after this change?

1

There are 1 answers

4
uselpa On BEST ANSWER

In the first version (circle-fractal (/ size 2) colour) is evaluated only if size > CUT-OFF. In the second it's called regardless of size. This way you lost your recursion base case.

Try:

(define (circle-fractal size colour)
  (define full-circle (circle size CIRCLE-MODE colour))
  (cond [(<= size CUT-OFF) full-circle]
        [else
         (define half-circle (circle-fractal (/ size 2) colour))
         (overlay/align "middle" "middle" 
                        full-circle
                        (beside half-circle half-circle))]))