Các macro có được mở rộng khi tệp được biên dịch không?


13

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-compilekhông?

Câu trả lời:


13

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 defuns, defmacros, lambdas, đề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 lambdas 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 lambdas .

Đâ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.


7

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ápkhô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 .


Những điểm rất tốt cần được ghi nhớ khi viết hoặc sử dụng macro.
Sean Allred

"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." Cho đến một tuần trước, pack.el đã có một lỗi hoàn toàn phá vỡ cài đặt gói trong các tình huống phụ thuộc macro hoàn toàn hợp pháp.
Malabarba

@Malabarba Chăm sóc để cung cấp chi tiết?
lunaryorn

@lunaryorn Ở đây bạn đi . Vấn đề nhỏ khó chịu.
Malabarba

1
@lunaryorn Tôi đồng ý các macro là nguy hiểm (tôi thậm chí sẽ chỉnh sửa câu trả lời của mình để nghe ít khen ngợi hơn :), nhưng tôi không nghĩ rằng lỗi đó là một ví dụ cụ thể của nó. Lỗi đó có các biểu hiện khác (ít trầm trọng hơn) không liên quan đến macro. Nó cũng gây ra vấn đề với các phụ thuộc chức năng.
Malabarba
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.