Hãy nói rằng tôi chạy sauphụ thêm vào kết quả của một "loop-thu thập" trong Lisp
(loop for i to 4 collect i)
Sau đó, tôi nhận được một danh sách (0 1 2 3 4)
. Bây giờ, nếu tôi muốn nối thêm thứ gì đó vào kết quả, tôi có thể sử dụng rplacd
trên phần tử last
của nó, nhưng vì danh sách Lisp là các danh sách liên kết, nên nó không hiệu quả lắm. Ở đây danh sách rất nhỏ, nhưng nó chỉ là một ví dụ.
Tuy nhiên, vì cơ sở vòng lặp trả về danh sách theo thứ tự tăng dần, nó phải theo dõi con trỏ đến phần tử cuối cùng và cập nhật kết quả bằng rplacd
hoặc tương đương. Một macroexpand-all
cho thấy đó là những gì CCL làm, và có lẽ là các lisps khác nữa.
Câu hỏi: Có cách nào để sử dụng "con trỏ" này trong mệnh đề finally
không? Nó sẽ cho phép một để thêm một cái gì đó cho kết quả, mà đôi khi hữu ích.
Tất nhiên, thật dễ dàng để mã hóa máy móc con trỏ, nhưng nó không quá đẹp. Ví dụ: thông tin sau đây sẽ thêm danh sách e
vào danh sách (0 1 ... n)
.
(defun foo (n e)
(let* ((a (list nil)) (tail a))
(loop for i to n
do (rplacd tail (setf tail (list i)))
finally (rplacd tail (setf tail e))
(return (cdr a)))))
Tôi chắc chắn vẫn còn nhiều điều cần tìm hiểu, đặc biệt là trên ** vòng lặp ** :-) –
@ Jean-ClaudeArbaut: Vì bạn đã phát hiện ra rằng việc triển khai 'LOOP' theo dõi các khuyết điểm cuối cùng và xác minh macro mở rộng mã , có vẻ như bạn đang khởi đầu tốt. ;-) –
Tôi thích điều này nhiều hơn tôi. Đó là một giải pháp sạch hơn nhiều (chỉ cần thêm một sự lặp lại thêm và làm một cái gì đó đặc biệt), ** và ** bạn nhận được sự trở lại tiềm ẩn của danh sách. Đây là câu trả lời tôi chấp nhận. –