Monday, January 02, 2006

CLisp Circular List

อ่านเจอใน Using Circular Structures in CL

คำสั่ง nconc ใช้สำหรับการเชื่อม list 2 อันเข้าด้วยกัน
โดยมันจะไปเปลี่ยน pointer ตัวสุดท้ายของ list อันแรก
(ซึ่งปกติชี้ไปที่ nil อยู่) ให้เปลี่ยนไปชี้ที่ element แรกของ
list ตัวที่ 2

CL-USER> (setf first-list '(1 2 3))
(1 2 3)
CL-USER> (nconc first-list '(4 5 6))
(1 2 3 4 5 6)
CL-USER> first-list
(1 2 3 4 5 6)
CL-USER>


จะเกิดอะไรขึ้น ถ้าเราสั่ง (nconc first-list first-list)

CL-USER> (nconc first-list first-list)
#1=(1 2 3 4 5 6 . #1#)

น่าสนใจมาก เมื่อ pointer ตัวสุดท้ายมาชี้ที่ element ตัวแรก
ก็เลยเกิดเป็น circular list ขึ้นมา

ทดลองสั่ง loop 10 ครั้งดู

CL-USER> (loop for i from 1 to 10
do (format t "~a~%" (elt first-list i)))
2
3
4
5
6
1
2
3
4
5
NIL

elt คือคำสั่งที่ใช้ access element ลำดับที่ต้องการ จาก list
เช่น (elt '(1 2 3) 1) จะได้ 2 ออกมา

จะเห็นว่า เราสามารถ loop ไปใน array นี้ได้ไม่รู้จบ

ที่นี้มันจะมาเป็น feature ได้ตรงไหน
มีตัวอย่างหนึ่งของ Thomas A. Russ เขาเขียนเป็น sample ให้ดู
เริ่มด้วย

(defun circular-list (&rest elements)
(let ((backbone (copy-list elements)))
(nconc backbone backbone)))

(defvar *days* (circular-list 'mon 'tue 'wed 'thur 'fri 'sat 'sun))

มีการกำหนด function ที่ชื่อ circular-list
ซึ่งการทำงานภายในก็คือการสั่ง nconc
ส่วน variable *days* ก็คือ circular list ของ วันในสัปดาห์

ที่นี้ลองดู function นี้
(defun days-of-month (n-days starting-day)
(loop for d from 1 to n-days
as day in (member starting-day *days*)
do (format t "The ~:R is a ~:(~A~).~%" d day)))


ทดลองสั่งทำงานดู
CL-USER> (days-of-month 15 'mon)
The first is a Mon.
The second is a Tue.
The third is a Wed.
The fourth is a Thur.
The fifth is a Fri.
The sixth is a Sat.
The seventh is a Sun.
The eighth is a Mon.
The ninth is a Tue.
The tenth is a Wed.
The eleventh is a Thur.
The twelfth is a Fri.
The thirteenth is a Sat.
The fourteenth is a Sun.
The fifteenth is a Mon.
NIL

Related link from Roti

No comments: