Apakah makro diperluas ketika file dikompilasi?


13

Saya memiliki makro yang perlu diperluas pada setiap contoh penggunaan waktu kompilasi. Apakah ada cara saya bisa menentukan ini tanpa melalui basis kode dan dengan hati-hati menutup setiap panggilan eval-when-compile?

Jawaban:


13

Semua makro yang dapat dijangkau oleh byte-compiler diperluas selama kompilasi. "Reachable" pada dasarnya berarti tidak dikutip.

Badan defuns, defmacros, lambdas, semuanya byte-dikompilasi ketika file sumber yang mengandungnya adalah byte-dikompilasi. Jadi ya, makro apa pun di dalamnya akan diperluas, asalkan mereka tidak ada di dalam kuotasi ( '). Sebuah kesalahan yang sangat umum adalah untuk membungkus lambdadalam kutipan dan, pada kenyataannya, itu sebabnya Anda harus tidak pernah mengutip Anda lambdas .

Ini adalah salah satu keuntungan besar dari makro, selama mereka ditulis dengan baik, mereka tidak berdampak pada kinerja runtime. Keuntungan lainnya adalah kekuatan dan keserbagunaan mereka, tentu saja. Kerugiannya adalah Anda memanipulasi sintaks, bukan objek, jadi ada banyak ruang untuk masalah, beberapa tidak terduga, yang lain tidak dapat dihindari.


7

Seperti yang sudah dijelaskan Malabarba, makro diperluas selama kompilasi byte. Jika file tidak dikompilasi, makro diperluas ketika file dimuat (ingin ekspansi makro).

Namun, jangan mengandalkan ini. Itu gaya yang sangat buruk. Anda umumnya tidak dapat mengharapkan bahwa kode yang menggunakan makro Anda sebenarnya dikompilasi, dan Anda umumnya harus menjalankan kode sesedikit mungkin selama kompilasi. Secara khusus, gunakan makro jarang dan hanya jika tidak ada cara lain. Sebagai aturan praktis, gunakan makro hanya untuk sintaks , dan tidak pernah untuk semantik (atau fungsionalitas).

Makro adalah abstraksi yang bocor. Ekspansi mereka dikodekan ke dalam kode target pada waktu kompilasi, dan tidak dapat diubah secara retrospektif. Kode target selanjutnya tergantung pada implementasi spesifik makro pada waktu ekspansi. Secara khusus, itu tergantung pada semua API internal yang digunakan dalam tubuh makro.

Akibatnya, Anda tidak dapat mengubah API ini, atau apa pun yang menjadi dasar ekspansi makro, tanpa melanggar kode apa pun yang dikompilasi terhadap makro Anda.

Penggunaan makro yang liberal untuk fungsionalitas membuka jalan menuju neraka ketergantungan .


Poin yang sangat baik untuk diingat ketika menulis atau menggunakan makro.
Sean Allred

"Penggunaan liberal makro untuk fungsionalitas membuka jalan menuju neraka ketergantungan." Sampai seminggu yang lalu, package.el memiliki bug yang benar-benar merusak instalasi paket di bawah situasi ketergantungan makro yang sah.
Malabarba

@Malabarba Care memberikan detail?
lunaryorn

@Lunaryorn Ini dia . Masalah kecil yang jahat.
Malabarba

1
@Lunaryorn Saya setuju makro berbahaya (saya bahkan akan mengedit jawaban saya untuk terdengar kurang memuji :), tapi saya tidak berpikir bug itu adalah contoh spesifik dari itu. Bug itu memiliki manifestasi lain (kurang memberatkan) yang tidak melibatkan makro sama sekali. Ini juga menyebabkan masalah dengan dependensi fungsi.
Malabarba
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.