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
?
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:
Semua makro yang dapat dijangkau oleh byte-compiler diperluas selama kompilasi. "Reachable" pada dasarnya berarti tidak dikutip.
Badan defun
s, defmacro
s, lambda
s, 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 lambda
dalam kutipan dan, pada kenyataannya, itu sebabnya Anda harus tidak pernah mengutip Anda lambda
s .
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.
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 .