我正在使用一个基于CL的音乐作曲可视化编程环境。我尝试创建一个函数,当给定3个元素(1 2 3)时,将返回1,2,3,1,2,3等,每次评估时逐个输出序列中的数字。书籍《Common Lisp a Gentle Introduction》简要提到可以使用“#=”符号表示法创建循环列表,但没有详细介绍如何使用它们。 请注意,我可以使用专门设计的对象在程序中插入实际的Lisp代码。
我正在使用一个基于CL的音乐作曲可视化编程环境。我尝试创建一个函数,当给定3个元素(1 2 3)时,将返回1,2,3,1,2,3等,每次评估时逐个输出序列中的数字。书籍《Common Lisp a Gentle Introduction》简要提到可以使用“#=”符号表示法创建循环列表,但没有详细介绍如何使用它们。 请注意,我可以使用专门设计的对象在程序中插入实际的Lisp代码。
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
circular
的定义中不需要返回items
,因为setf
会自动将其返回。 - anonymous#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)))
pop
做的就是我想要的事情。这就是当一个Schemer试图写CL时会发生的事情。;-)) - C. K. Young首先,您需要让打印机知道要识别循环列表而不是尝试打印整个列表:
(setf *print-circle* t)
接下来,你可以使用“#=”符号创建一个循环列表:
(setq x '#1=(1 2 3 . #1#))
这里是一个在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函数来添加、删除和访问项目。我认为我提供的已经足够展示你在定义这种循环列表的任何函数中需要做什么。在Listener中,这对我来说似乎是有效的。