问题
In Scheme/Lisp I am trying to make a function that converts a list into a circular list. Therefore, I believe I need to construct an infinite stream in which the tail of the list points to the head of the list.
Here is my code so far:
(define (rotate-list l1 l1copy)
(if (null? (force (cdr l1)))
(cons (car l1) (delay l1copy)))
(cons (car l1) (delay (rotate-list (force (cdr l1)) l1copy))))
All help is greatly appreciated.
回答1:
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. :-)
来源:https://stackoverflow.com/questions/14678943/scheme-streams-and-circular-lists