Scheme streams and circular lists

﹥>﹥吖頭↗ 提交于 2019-12-24 08:03:58

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!