Tôi có một macro cần được mở rộng ở mọi trường hợp sử dụng thời gian biên dịch của nó. Có cách nào để tôi có thể chỉ định điều này là như vậy mà không cần thông qua cơ sở mã và cẩn thận gói từng cuộc gọi với eval-when-compile
không?
Tôi có một macro cần được mở rộng ở mọi trường hợp sử dụng thời gian biên dịch của nó. Có cách nào để tôi có thể chỉ định điều này là như vậy mà không cần thông qua cơ sở mã và cẩn thận gói từng cuộc gọi với eval-when-compile
không?
Câu trả lời:
Tất cả các macro có thể truy cập bằng trình biên dịch byte được mở rộng trong quá trình biên dịch. "Có thể tiếp cận" về cơ bản có nghĩa là không được trích dẫn.
Phần thân của defun
s, defmacro
s, lambda
s, đều được biên dịch byte khi tệp nguồn chứa chúng được biên dịch byte. Vì vậy, có, bất kỳ macro nào bên trong chúng sẽ được mở rộng, miễn là chúng không nằm trong trích dẫn ( '
). Một sai lầm rất phổ biến là để bọc lambda
s trong một báo giá và, trên thực tế, đó là lý do tại sao bạn nên không bao giờ trích dẫn của bạn lambda
s .
Đây là một trong những lợi thế lớn của macro, miễn là chúng được viết tốt, chúng không có tác động đến hiệu suất thời gian chạy. Ưu điểm khác là sức mạnh và tính linh hoạt của họ, tất nhiên. Nhược điểm là bạn đang thao tác cú pháp, không phải đối tượng, vì vậy có rất nhiều chỗ cho các vấn đề, một số bất ngờ, một số khác không thể tránh khỏi.
Như Malabarba đã giải thích, các macro được mở rộng trong quá trình biên dịch byte. Nếu một tệp không được biên dịch, macro sẽ được mở rộng khi tệp được tải (mở rộng macro háo hức).
Đừng dựa vào điều này, mặc dù. Đó là phong cách rất xấu. Nói chung, bạn không thể mong đợi rằng mã sử dụng macro của bạn thực sự được biên dịch và bạn thường nên chạy càng ít mã càng tốt trong quá trình biên dịch. Cụ thể, sử dụng macro khan hiếm và chỉ khi không có cách nào khác. Theo nguyên tắc thông thường, chỉ sử dụng macro cho cú pháp và không bao giờ cho ngữ nghĩa (hoặc chức năng).
Macro là một trừu tượng rò rỉ. Sự mở rộng của chúng được mã hóa cứng vào mã đích trong thời gian biên dịch và không thể thay đổi hồi cứu. Mã đích sau đó phụ thuộc vào việc triển khai cụ thể của macro tại thời điểm mở rộng. Cụ thể, nó phụ thuộc vào tất cả các API nội bộ được sử dụng trong phần thân macro.
Do đó, bạn không thể thay đổi bất kỳ API nào này hoặc bất kỳ điều gì mà việc mở rộng macro phụ thuộc vào, mà không phá vỡ bất kỳ mã nào được biên dịch theo macro của bạn.
Việc sử dụng macro một cách tự do cho chức năng mở đường đến địa ngục phụ thuộc .