2015-10-30 22 views
10

Tôi muốn rebind một biến đặc biệt bên trong một vòng lặp. Bây giờ, thông thường, điều này được thực hiện bằng cách sử dụng let.Ràng buộc Lisp thường gặp trong vòng lặp Macro

(let ((*read-eval* nil)) 
    (do-something-here)) 

Nhưng kể từ khi loop vĩ mô có những đẹp with khoản, tôi nghĩ rằng tôi có thể có thể làm như vậy trong đó. Biểu thức (macroexpand '(loop with *read-eval* = nil)) kết thúc mở rộng liên kết đến let, do đó, nó chắc chắn sẽ hoạt động trên thực hiện của tôi một cách cụ thể. Nhưng tôi không thể tìm thấy bất kỳ điều gì trong số the standard cho biết rằng đây là hành vi được chuẩn hóa. Vì vậy, tôi cho rằng, câu hỏi của tôi là thế này:

triển khai
(loop with *read-eval* = nil 
     for i from 1 to 10 
     do (something-involving-the-read-function)) 

có phù hợp với yêu cầu sửa đổi các *read-eval* biến hiện có, hoặc là có một rủi ro mà họ có thể tạo ra một biến từ vựng mới cùng tên?

Trả lời

7

*read-eval* là biến toàn cầu đặc biệt. Không có cách nào để hoàn tác điều đó, tức là, tạo một liên kết từ vựng cục bộ cho nó.

with khoản được mô tả như sử dụng bindings (như trái ngược với chỉ thiết) có nghĩa là, quả thật vậy, khi vòng lặp được thực hiện, chúng tôi sẽ trở lại giá trị ban đầu (để trả lời @ joshua-may câu hỏi).

Hãy để chúng tôi suy nghĩ hợp lý. (loop with foo = nil ...) chắc chắn thiết lập một ràng buộc cho foo. Vì vậy, đối với (loop with *read-eval* = nil ...)không phải để thiết lập ràng buộc đó, việc triển khai phải kiểm tra (tại thời gian mở rộng macro hoặc biên dịch) cho dù *read-eval* sẽ là dynamic variable khi chạy. Điều này nghe có vẻ điên rồ.

+2

Điều này đúng, nhưng vẫn không rõ ràng rằng ** vòng lặp ** có phải rebind, thay vì chỉ gán. Chúng ta có biết rằng khi vòng lặp được thực hiện, chúng ta sẽ quay lại giá trị ban đầu? Tôi khá chắc chắn câu trả lời là có, dựa trên http://www.lispworks.com/documentation/HyperSpec/Body/06_abb.htm, mà nói rằng các biến chấm dứt tồn tại bên ngoài vòng lặp. Phrasing không hoạt động đặc biệt tốt cho các biến đặc biệt, nhưng có vẻ như cách giải thích hợp lý duy nhất là một ràng buộc địa phương của tên, có nghĩa là * let * (hoặc * lambda *, v.v.). –

Các vấn đề liên quan