我正在使用基于CL的音乐作品的可视化编程环境。我正在尝试创建一个函数,当给出时,说3个元素(1 2 3)将返回1,2,3,1,2,3等,每次评估时都有一个数字。本书 Common Lisp a Gentle Introduction 简要提到,可以使用尖锐相等的符号创建循环列表,但不会详细介绍如何使用它们。 请记住,我可以使用专门为此设计的对象在程序中插入实际的Lisp代码。
答案 0 :(得分:13)
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#)
示例:
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
也:
CL-USER 6 > '#1=(1 2 3 . #1#)
#1=(1 2 3 . #1#)
添加了一些CLOS:
(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
答案 1 :(得分:10)
以Sharpsign Equal-Sign表示法,它写为#0=(1 2 3 . #0#)
。
这是一个从给定参数创建这样一个列表的函数:
(defun circular (first &rest rest)
(let ((items (cons first rest)))
(setf (cdr (last items)) items)))
然后,调用(circular 1 2 3)
将返回您想要的循环列表。只需使用car
和cdr
无限制地迭代这些元素。
如果你真的想要一个不带参数的迭代器函数并返回每个调用的下一个项目,那么你可以这样做:
(defun make-iter (list)
(lambda ()
(pop list)))
答案 2 :(得分:0)
这是在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")
我没有提供defun功能来添加,删除和访问项目。我想我所提供的内容足以显示您在为这种循环列表定义的任何函数中需要执行的操作。这在我看来是在听众中工作。