Circular list in Common Lisp

走远了吗. 提交于 2019-11-28 13:31:28
CL-USER 3 > (defun circular (items)
              (setf (cdr (last items)) items)
              items)
CIRCULAR

CL-USER 4 > (setf *print-circle* t)
T

CL-USER 5 > (circular (list 1 2 3))
#1=(1 2 3 . #1#)

Example:

CL-USER 16 > (setf c1 (circular (list 1 2 3)))
#1=(1 2 3 . #1#)

CL-USER 17 > (pop c1)
1

CL-USER 18 > (pop c1)
2

CL-USER 19 > (pop c1)
3

CL-USER 20 > (pop c1)
1

also:

CL-USER 6 > '#1=(1 2 3 . #1#)
#1=(1 2 3 . #1#)

With a bit of CLOS added:

(defclass circular ()
  ((items :initarg :items)))

(defmethod initialize-instance :after ((c circular) &rest initargs)
  (setf (slot-value c 'items) (circular (slot-value c 'items))))

(defmethod next-item ((c circular))
  (prog1 (first (slot-value c 'items))
    (setf (slot-value c 'items)
          (rest (slot-value c 'items)))))

CL-USER 7 > (setf circ1 (make-instance 'circular :items (list 1 2 3)))
#<CIRCULAR 40200017CB>

CL-USER 8 > (next-item circ1)
1

CL-USER 9 > (next-item circ1)
2

CL-USER 10 > (next-item circ1)
3

CL-USER 11 > (next-item circ1)
1

CL-USER 12 > (next-item circ1)
2

In Sharpsign Equal-Sign notation, it's written as #0=(1 2 3 . #0#).

Here's a function which creates such a list from the given arguments:

(defun circular (first &rest rest)
  (let ((items (cons first rest)))
    (setf (cdr (last items)) items)))

Then, calling (circular 1 2 3) will return the circular list you wanted. Just use car and cdr to iterate through the elements ad infinitum.

And if you really want an iterator function that takes no arguments and returns the next item for each call, here's how you might do it:

(defun make-iter (list)
  (lambda ()
    (pop list)))
Indinfer

Here is an idea worked out for a circular list in Lisp.

;;; Showing structure of the list
;;; (next prev is-end val)

; create items
setf L-0 (L-1 L-3 t "L-0 sentry")  ; this will be the sentry item so know where to stop
setf L-1 (L-2 L-0 nil "L-1")
setf L-2 (L-3 L-1 nil "L-2")
setf L-3 (L-0 L-2 nil "L-3")

; how to access L-2 from L-0
eval (first (eval (first L-0)))

; result: (L-3 L-1 NIL "L-2")

I'm not giving defun functions to make adding, removing, and accessing the items. I'm thinking that what I gave is enough to show what you need to do in any functions you define for this kind of circular list. This appeared to me to work in the Listener.

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