Pracuję wykorzystując wizualne środowisko programistyczne do kompozycji muzycznej opartej na CL. Próbuję utworzyć funkcję, która po powiedzeniu, że 3 elementy (1 2 3) zwrócą 1, 2, 3, 1, 2, 3 itd., Jedną liczbę w czasie za każdym razem, gdy jest oceniany. Książka Common Lisp a Gentle Wstęp, krótko wspomina, że możliwe jest tworzenie okrągłych list przy użyciu ostro-równomiernej notacji, ale nie wchodzi w szczegóły, jak z nich korzystać. Należy pamiętać, że mogę wstawić rzeczywisty kod Lisp w programie przy użyciu specjalnie do tego celu zaprojektowanego obiektu.Okólnik w Common Lisp
Odpowiedz
W notacji Sharpsign Equal-Sign jest to napisane jako #0=(1 2 3 . #0#)
.
Oto funkcja, która stwarza taką listę z podanych argumentów:
(defun circular (first &rest rest)
(let ((items (cons first rest)))
(setf (cdr (last items)) items)))
Następnie, nazywając (circular 1 2 3)
zwróci listę okrągły chciałeś. Po prostu użyj car
i cdr
do iteracji elementów w nieskończoność.
A jeśli naprawdę chcesz funkcję iterator, która pobiera żadnych argumentów i zwraca następną pozycję dla każdego połączenia, oto jak można to zrobić:
(defun make-iter (list)
(lambda()
(pop list)))
Możesz użyć PROG1 zamiast LET. –
@ThomasBartscher Dzięki! Jest teraz zaimplementowany. (Właściwie to popatrzyłem na odpowiedź Rainera i wydaje mi się, że 'pop' robi to samo, co ja po.) Tak dzieje się, gdy Schemat próbuje napisać CL. ;-)) –
Huh, nie myślałem o tym. Miły! –
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#)
Przykład:
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
także:
CL-USER 6 > '#1=(1 2 3 . #1#)
#1=(1 2 3 . #1#)
Z dodanym bitem 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
Dziękuję, że to bardzo pomocne. –
Czy są jakieś książki lub witryny, które sugerujesz, które pomogłyby mi dowiedzieć się więcej o tego typu rzeczach? –
Istnieje sekcja w Let Over Lambda w wyrażeniach cyklicznych: http://letoverlambda.com/index.cl/guest/chap4.html#sec_5 –
Oto pomysł opracowany na okrągłą listę w 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")
Nie zapewniam funkcji defun do dodawania, usuwania i uzyskiwania dostępu do przedmiotów. Myślę, że to, co podałem, wystarczy, aby pokazać, co trzeba zrobić w dowolnej funkcji zdefiniowanej dla tego rodzaju listy okrężnej. Wydawało mi się, że działa w słuchaczu.
Zobacz także [Lisp cyclic lists] (http://stackoverflow.com/q/15536564/1281433) i [Przykład makra czytnika książek Sharpsign Equal-Sign] (http://stackoverflow.com/q/12649290/1281433). –