Làm thế nào để đánh giá các biến trước khi thêm chúng vào danh sách?


30

Dưới đây rõ ràng không hoạt động và do đó câu hỏi này.

Làm thế nào để tôi sửa mã dưới đây để giá trị somelisttrở thành '(("abc" . 123))?

(setq x "abc")
(setq y 123)
(setq somelist nil)
(add-to-list 'somelist '(x . y))

5
Bạn đã thử khai thác chưa? Hãy thử `(,x . ,y).
Dân

Ah, đó là những gì tôi đã bỏ lỡ. Tôi không biết google để làm gì :). Tôi đã thử (add-to-list 'somelist '(,x . ,y))nhưng quên backquote.
Kaushal Modi

Các câu hỏi được coi là trùng lặp của câu hỏi này tái diễn rất thường xuyên. Ai đó có thể đưa ra một cách để làm cho người mới bắt đầu rõ ràng hơn rằng câu hỏi / câu trả lời này là những gì họ đang tìm kiếm? Tôi nghi ngờ một phần của vấn đề là tiêu đề của câu hỏi này chỉ có ý nghĩa nếu bạn đã biết nguyên nhân gốc rễ của vấn đề (tức là bạn biết câu trả lời). Tôi đang cố gắng tưởng tượng mình là một người dùng không biết rằng các biến cần phải được đánh giá và thậm chí ít ý tưởng hơn về "trích dẫn" nghĩa là gì, nhưng sắp hết. @Đã vẽ?
Stefan

@stefan: Không giống như trường hợp có thông báo lỗi (có thể được sử dụng trong tiêu đề câu hỏi của cộng đồng Q + A), lỗi, nếu có, dẫn đến việc trích dẫn điều gì đó cần được đánh giá (và đây là một trường hợp cụ thể trường hợp đó) có thể là xa của trang web của trích dẫn. Thông thường hơn, không có lỗi (Emacs) - chỉ là hành vi không tương ứng với những gì người dùng muốn.
vẽ

@Stefan: Không có tiêu đề câu hỏi tuyệt vời nào cho tâm trí này. Nhưng ít nhất chúng ta có thể đặt ra một câu hỏi trực tiếp giải quyết nó, bao gồm cả trường hợp "bình thường" yêu cầu xóa dấu ngoặc kép và trường hợp yêu cầu khai thác. Một Q tốt, bao gồm các trường hợp như vậy, và một câu trả lời tốt bao gồm chúng, sẽ hữu ích. Nhưng đối với việc tìm Q là trùng lặp: không có thông báo lỗi trong tiêu đề Q, nó yêu cầu đọc toàn bộ câu hỏi và biết cách tìm bản sao để trỏ đến.
vẽ

Câu trả lời:


30

Vấn đề chung là bạn cần xyđược đánh giá trước khi chúng được chèn vào somelist. Vấn đề với các danh sách trích dẫn (với 'như cú pháp reader)quotelà một hình thức đặc biệt mà không đánh giá đối số của nó. Theo các chuỗi:

(quote ARG)

Trả về đối số, mà không đánh giá nó. (quote x)năng suất x. Cảnh báo: quotekhông xây dựng giá trị trả về của nó, mà chỉ trả về giá trị được xây dựng trước bởi trình đọc Lisp ...

Do đó, bạn có cần phải backquote hoặc sử dụng một hàm đánh giá lại các đối số.

Backquote cho phép bạn đánh giá các thành phần của danh sách backquote một cách chọn lọc với ,cú pháp:

(setq x "x-val" y "y-val" z "z-val" somelist nil)
'(x  y z)                            ; => (x y z)
`(x ,y z)                            ; => (x "y-val" z)
(add-to-list 'somelist `(x y ,z))    ; => ((x y "z-val"))

Thay phiên, bạn có thể sử dụng cons(như @tarsius gợi ý trong câu trả lời của anh ấy) hoặc, cho một số phần tử tùy ý , list:

(add-to-list 'somelist (cons x y))   ; => (("x-val" . "y-val"))
(setq somelist nil)                  ; reset
(add-to-list 'somelist (list x y z)) ; => (("x-val" "y-val" "z-val"))

Việc sử dụng phụ thuộc vào những gì bạn cần làm với các yếu tố.


19

Không trích dẫn ô khuyết điểm, vì các biểu thức được trích dẫn không được đánh giá. Đó chính xác là lý do tại sao một trích dẫn - để ngăn chặn đánh giá. Nhưng đó không phải là điều bạn muốn, vì vậy đừng.

Thay vào đó sử dụng biểu mẫu tạo một ô khuyết từ hai giá trị được đánh giá, các đối số của nó.

(cons x y)

Tất nhiên bạn cũng có thể quasiquote nhưng điều đó không thực sự có ý nghĩa ở đây, và trông tệ hơn. Chỉ sử dụng `,khi điều đó cải thiện khả năng đọc, tức là khi thực hiện một việc phức tạp hơn là xây dựng một ô khuyết điểm hoặc thêm một nguyên tử hoặc danh sách ở đầu một số danh sách hiện có.

Sử dụng chuẩn tinh nó sẽ trông như thế này:

`(,x . ,y)

Điều này tệ hơn bởi vì nó sử dụng cú pháp bổ sung không cần thiết trong trường hợp này và làm xáo trộn consđang được sử dụng.


3
Điểm tốt trên consing. Quasiquote gây ấn tượng với tôi là kiểm soát chi tiết hơn các nội dung danh sách hơn là dễ đọc, nhưng tôi đồng ý rằng trường hợp sử dụng có ý nghĩa cons.
Dan

Cảm ơn bạn vì câu trả lời. Đó là một khoảnh khắc TIL tuyệt vời cho tôi. Tôi đã mù quáng đặt dấu ngoặc kép trước danh sách và khuyết điểm.
Kaushal Modi

@Dan, cũng có - và không. Quasiquoting không thể làm bất cứ điều gì mà bạn không thể làm gì với chỉ cons, listnconc. Ngoại trừ việc xinh hơn. Đó là đường cú pháp hữu ích khi bạn cần "kiểm soát chi tiết nội dung danh sách" (như trong "làm một việc gì đó phức tạp hơn việc thêm một nguyên tử hoặc danh sách lúc đầu"). Và lợi ích bổ sung của việc sử dụng đường cú pháp đó là: khả năng đọc. Quasiquote không cung cấp cho bạn thêm quyền kiểm soát chi tiết - nó chỉ cho phép bạn làm điều tương tự với ít lỗi hơn trong lần thử đầu tiên. :-)
tarsius
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.