Apakah dukungan makro dalam bahasa pemrograman dianggap berbahaya?

8

Pelecehan pertama yang muncul di pikiran saya di C adalah:

#define if while 

Tetapi pada saat yang sama sangat berguna dan kuat ketika digunakan dengan benar.

Hal serupa terjadi dengan makro Lisp Umum.

Mengapa tidak semua bahasa pemrograman mendukung makro seperti ini dan apa alternatifnya?

Apakah mereka dianggap berbahaya?

OscarRyz
sumber
20
Pisau berbahaya. Alternatifnya adalah mencoba memotong benda dengan sendok.
Matt Ellen
1
@ Mat atau untuk memberikan pegangan yang baik.
OscarRyz

Jawaban:

15

Saya berpendapat bahwa jika suatu bahasa memiliki makro, mereka harus direncanakan dengan baik dan bagian yang tidak terpisahkan dari bahasa dan bukan dari kompiler .

Contoh, sistem makro Lisp adalah fitur bahasa terintegrasi yang sangat kuat dan tunduk pada semua aturan dan peraturan Lisp itu sendiri.

Contoh tandingan, sistem makro C / C ++ terpisah dari bahasa dan dibangun ke dalam kompiler. Hasilnya adalah Anda tidak terbatas pada kendala bahasa Anda dan dapat membuat kode yang tidak valid dan mendefinisikan kembali kata kunci spesifik bahasa.

Pada akhirnya, ada beberapa bahasa yang tidak memiliki fitur makro - tetapi fitur-fitur itu tidak terlalu dilewatkan. Itu semua tergantung pada seberapa ekspresif suatu bahasa, dan apakah ia memiliki pendekatan alternatif untuk meta-pemrograman. Meta-pemrograman hanyalah cara untuk memastikan bahwa ketika Anda melakukan X, X dilakukan dengan cara yang sama di seluruh aplikasi.

Berin Loritsch
sumber
4
Lebih buruk lagi, preprosesor C bahkan bukan bagian dari kompiler.
1
Apa perbedaan yang Anda coba gambarkan di sini antara "bahasa" dan "kompiler"? Sistem makro C didefinisikan dalam standar bahasa, makro Lisp sebenarnya diperluas oleh kompilator Lisp, dan implementasi bahasa apa pun didefinisikan, ketika semua dikatakan dan dilakukan, oleh kompiler dan perpustakaan standar. Oleh karena itu, frasa "terpisah dari bahasa dan dibangun ke dalam kompiler" tidak masuk akal. Mungkin perbedaan yang Anda cari adalah bahwa macro C diimplementasikan di front-end kompiler, dan macro Lisp di back-end?
Mason Wheeler
Perbedaannya berkaitan dengan konsistensi bahasa. Pikirkan seperti ini, Anda berencana pergi ke negara asing dan Anda harus belajar berbicara bahasa Prancis untuk pergi ke berbagai tempat dan membeli makanan. Ketika berhadapan dengan bea cukai, Anda lebih baik belajar bahasa Swedia atau hanya berurusan dengan bahasa Prancis. Makro prekompiler C keduanya berbeda secara sintaksis dan secara tata bahasa dari pada standar C. Tantangan kognitif kemudian mencari tahu apa yang akan dilakukan oleh bahasa lain terhadap program C standar Anda. Dalam beberapa kasus itu mudah, tetapi saya telah melihat seluruh frase kode sebagai definisi makro. Sekarang debug itu.
Berin Loritsch
8

Makro C dan makro Lisp sama sekali berbeda. Makro C diperluas menggunakan substitusi string sebelum pemrosesan lainnya dilakukan. Makro Lisp diperluas setelah teks input telah diuraikan menjadi pohon sintaks 1 , dan dapat menggunakan seluruh bahasa selama ekspansi. Dengan Lisp macro, Anda tidak hanya dapat melakukan hal-hal bodoh seperti #define begin {, tetapi Anda dapat menentukan struktur kontrol Anda sendiri, dan bahkan mengisi array pada waktu kompilasi menggunakan kode apa pun yang Anda inginkan.

Salah satu alasan untuk tidak memasukkan makro adalah bahwa sesuatu yang lebih rumit daripada penggantian string sederhana bisa sangat sulit untuk digunakan dalam bahasa dengan sintaks C-style. Keluhan lain tentang makro adalah mereka dapat membuat kode lebih sulit dibaca, yang bisa benar jika tidak diterapkan dengan terampil. Makro Lisp yang ditulis dengan baik sebenarnya dapat membuat kode lebih mudah dibaca.

1 kecuali untuk makro baca, yang diperluas selama proses pembuatan pohon sintaksis.

Larry Coleman
sumber
2

Saya tidak berpikir ada alasan khusus mengapa mereka tidak didukung dalam beberapa bahasa, sama seperti mengapa beberapa sensitif huruf dan beberapa tidak. Biasanya tidak ada alasan, hanya keputusan yang diambil.

TAPI alasan mereka tidak termasuk pasti bukan keamanan. Itu

#define X Y

pernyataan mengubah semua X ke Y pada waktu kompilasi. Jika Anda dapat mengubah pernyataan #define, Anda bisa menyalin / mengganti sumber yang ingin Anda ubah dan kompilasi lagi.

Mike M.
sumber