Tôi đang dạy bản thân một số điều cần thiết hơn và đã gặp phải vấn đề sau:
Nếu tôi muốn đặt lại một biến danh sách, nó sẽ không được cập nhật sau lần đánh giá đầu tiên. Dưới đây là một số mã ví dụ:
(defun initilize ()
(setq example '(3)))
(defun modify ()
(initilize)
(message "%S" example)
(setcar example 2))
; M-x eval-buffer RET
(modify) ; message --> (3)
(modify) ; message --> (2)
(modify) ; message --> (2)
Tôi quan tâm đến hai điều. Đầu tiên là tìm hiểu thêm về những gì đang xảy ra "dưới mui xe", vậy tại sao nó hoạt động lần đầu tiên và thất bại trong các cuộc gọi tiếp theo?
Câu hỏi thứ hai và thiết thực hơn là làm thế nào để sắp xếp lại danh sách đúng cách hay có một cách phổ biến khác để làm một cái gì đó như thế?
Một cách giải quyết tôi thấy mình là sử dụng một danh sách được trích dẫn và đánh giá nội dung như thế này:
(setq example `(,3))
example
chưa bao giờ được khai báo là một biến, vì vậy setq
phải hành động như thể nó khai báo một biến mới, nhưng sau đó khi bạn gọi initialize
lại một biến mới đang được tạo, trong khi modify
nhớ lại biến cũ ... trong mọi trường hợp, đây không phải là một hành vi dự kiến, tuy nhiên, việc sử dụng setq
với một thứ chưa được giới thiệu trước đó như một biến cũng có thể không được xác định.
'(3)
được coi là một giá trị theo nghĩa đen, vì vậy một khi bạn (setcar '(3) 2)
, bất cứ khi nào bạn làm (defvar foo '(3))
hoặc (let ((foo '(3)))
như vậy, bạn có thể sẽ nhận được một giá trị foo
bằng '(2)
. Tôi nói "có khả năng" bởi vì hành vi này không được đảm bảo, đó là một loại tối ưu hóa mà người phiên dịch thực hiện bất cứ khi nào nó cảm thấy, một cái gì đó được gọi là loại bỏ hằng số phụ (một trường hợp cụ thể). Vì vậy, những gì abo-abo viết không chính xác là lý do. Nó giống như sửa đổi một chuỗi ký tự bằng chữ C (thường tạo cảnh báo).
'(some list)
để đượceq
đến'(some list)
- từng .There nói chung là không có bảo đảm trong Lisp rằng mã mà rõ ràng trích dẫn một danh sách lợi nhuận mới cấu trúc danh sách mỗi lần. Trong một số triển khai Lisp, nó có thể, hoặc đôi khi có thể. Trong những người khác, nó không bao giờ làm. Mã của bạn dù sao cũng không nên phụ thuộc vào bất kỳ hành vi nào như vậy từ việc triển khai. Nếu bạn muốn cấu trúc mới danh sách, sử dụnglist
hoặccons
hoặc tương đương.