No, you don't need streams to make a circular list.
There are two approaches to creating circular lists, the standard Scheme approach, and the Racket approach (since Racket's conses are immutable). I will look at examples using SRFI 1's circular-list
function. Here's the reference implementation:
(define (circular-list val1 . vals)
(let ((ans (cons val1 vals)))
(set-cdr! (last-pair ans) ans)
ans))
What that does is to find the last pair in the list of given values, and set-cdr!
s it back to the beginning of that list. Pretty straightforward, right?
In Racket, conses are immutable, so set-cdr!
does not exist. So instead, Racket does it this way:
(define (circular-list val1 . vals)
(let ([ph (make-placeholder #f)])
(placeholder-set! ph
(cons val1 (let loop ([vals vals])
(if (null? vals)
ph
(cons (car vals) (loop (cdr vals)))))))
(make-reader-graph ph)))
This uses Racket's make-reader-graph
function to handle the cycles. Very nifty. :-)