Metaprogramlama tam olarak nedir?


128

Java platformunda ployglot programlama üzerine TheServerSide hakkında bir makale okuyordum . Makaledeki bazı yorumlar, kod üretme yeteneği olarak meta programlamaya atıfta bulunur (belki de anında).

Metaprogramlama, anında kod üretme yeteneğini mi yoksa çalışma zamanında mevcut nesnelere yöntemler ve öznitelikleri enjekte etme yeteneği mi (Python, Ruby ve Groovy gibi bazı dinamik dillerin izin verdiği gibi).


7
Bu cevap ilginizi çekebilir stackoverflow.com/questions/2565572/…
ewernli

@ewernli: Bu cevap aslında buradaki cevapların hepsinden daha iyi!
JD

Yanıtlar:


100

Metaprogramlama, bir programın kendisi hakkında bilgi sahibi olduğu veya kendi kendini manipüle edebileceği çeşitli yolları ifade eder.

C # gibi dillerde yansıma, program kendisi hakkındaki bilgileri inceleyebildiği için bir metaprogramlama biçimidir. Örneğin, bir nesnenin tüm özelliklerinin bir listesini döndürmek.

ActionScript gibi dillerde, eval ("x" + i) gibi yeni programlar oluşturmak için çalışma zamanında işlevleri değerlendirebilirsiniz. DoSomething (), i 1 olduğunda x1 ve i 2 olduğunda x2 adlı bir nesneyi etkiler.

Son olarak, meta programlamanın diğer bir yaygın biçimi, programın önemsiz olmayan modalarda kendini değiştirebildiği zamandır. LISP bununla ünlüdür ve Paul Graham'ın yaklaşık on yıl önce savunduğu bir şeydir. Onun özel denemelerinden bazılarına bakmam gerekecek. Ancak fikir, programın durumuna bağlı olarak programın başka bir bölümünü değiştireceğidir. Bu, günümüzün en popüler dillerinde çok zor olan çalışma zamanında kararlar almak için bir esneklik düzeyi sağlar.

Düz montajda programlamanın güzel günlerinde, çalışma zamanında kendilerini değiştiren programların gerekli ve çok yaygın olduğunu da belirtmek gerekir.

Paul Graham'ın "Lisp'i Farklı Yapan Şey" makalesinden :

Birçok dilde makro denen bir şey vardır. Ancak Lisp makroları benzersizdir. Ve ister inanın ister inanmayın, yaptıkları parantezlerle ilgilidir. Lisp'in tasarımcıları, sırf farklı olsun diye tüm bu parantezleri dile koymadılar. Blub programcısına Lisp kodu tuhaf görünüyor. Ancak bu parantezlerin bir nedeni var. Lisp ile diğer diller arasındaki temel farkın dışa dönük kanıtıdır.

Lisp kodu, Lisp veri nesnelerinden oluşur. Ve kaynak dosyaların karakter içermesi ve dizelerin dil tarafından desteklenen veri türlerinden biri olması önemsiz anlamda değil. Lisp kodu, ayrıştırıcı tarafından okunduktan sonra, üzerinden geçebileceğiniz veri yapılarından oluşur.

Derleyicilerin nasıl çalıştığını anlarsanız, gerçekte olan şey Lisp'in tuhaf bir sözdizimine sahip olmasından ötürü Lisp'in sözdizimi olmadığı için. Diğer diller çözümlendiğinde derleyici içinde oluşturulan ayrıştırma ağaçlarına programlar yazarsınız. Ancak bu ayrıştırma ağaçlarına programlarınız için tamamen erişilebilir. Onları manipüle eden programlar yazabilirsiniz. Lisp'de bu programlara makro denir. Program yazan programlardır.

Program yazan programlar? Bunu ne zaman yapmak istersin? Cobol'da düşünürseniz çok sık değil. Lisp'de düşünürseniz her zaman. Burada güçlü bir makro örneği verebilseydim ve orada söyleyebilseydim daha uygun olur! Peki ya bu? Ama bilseydim, Lisp'i tanımayan birine anlamsız gelebilirdi; burada ne anlama geldiğini anlamak için bilmeniz gereken her şeyi açıklayacak yer yok. In Ansi Common Lisp ben geldiğince hızlı ileri gitmek çalıştı ve hatta bu yüzden sayfa 160 kadar makrolar alamadım.

Ama ikna edici olabilecek bir tür argüman sunabileceğimi düşünüyorum. Viaweb editörünün kaynak kodu muhtemelen yaklaşık% 20-25 makro idi. Makroları yazmak sıradan Lisp işlevlerinden daha zordur ve gerekmediklerinde bunları kullanmak kötü bir tarz olarak kabul edilir. Yani bu koddaki her makro, olması gerektiği için oradadır. Bunun anlamı, bu programdaki kodun en az% 20-25'inin başka bir dilde kolayca yapamayacağınız şeyler yaptığıdır. Blub programcısı, Lisp'in gizemli güçlerine dair iddialarıma kuşkuyla baksa da, bu onu meraklandırmalı. Bu kodu kendi eğlencemiz için yazmıyorduk. Rakiplerimizle aramıza teknik engeller koymak için elimizden geldiğince sıkı programlama yapan küçük bir girişimdik.

Şüpheli bir kişi, burada bir bağlantı olup olmadığını merak etmeye başlayabilir. Kodumuzun büyük bir kısmı diğer dillerde yapılması çok zor olan şeyler yapıyordu. Ortaya çıkan yazılım, rakiplerimizin yazılımının yapamadığı şeyleri yaptı. Belki bir çeşit bağlantı vardı. Bu konuyu takip etmenizi tavsiye ederim. Koltuk değneklerinde topallanan o yaşlı adam göründüğünden daha fazlası olabilir.


6
C ++ 'da şablon meta programlamayı unutmayın. İfadeleri yürütme ve derleme sırasında kararlar alma ve sonuçların statik olarak son çalıştırılabilir dosyada derlenmesini sağlama yeteneği.
Remy Lebeau

1
Beni şaşırttı in order to put technical barriers between us and our competitorsve bu doğru terbiye.
Evan Hu

4
Kendilerini manipüle eden programlar, tüm metaprogramların bir alt kümesidir. Metaprogramlama genel olarak sadece programları manipüle eden programlar anlamına gelir.
JD

55

Harika soru. Şu anda yanıtlardan hiçbirinin sorunuzu doğru yanıtlamadığını gördüğüme çok üzüldüm. Belki yardım edebilirim ...

Metaprogramlamanın tanımı gerçekten oldukça basittir: programları manipüle eden programlar anlamına gelir.

Kabul ettiğiniz yanıt, kendilerini manipüle eden programların olduğunu söylüyor. Bunlar aslında metaprogramlardır ancak tüm metaprogramların bir alt kümesidirler.

Herşey:

  • ayrıştırıcılar
  • Etki alanına özgü diller (DSL'ler)
  • Yerleşik etki alanına özgü diller (EDSL'ler)
  • Derleyiciler
  • Tercümanlar
  • Dönem yeniden yazanlar
  • Teorem kanıtlayıcılar

metaprogramlardır. Dolayısıyla, GCC derleyicisi bir metaprogramdır, CPython yorumlayıcısı bir metaprogramdır, Mathematica bilgisayar cebir sistemi bir metaprogramdır, Coq teorem programlayıcısı bir metaprogramdır vb.

Diğer cevaplar, metaprogramların diğer programları oluşturan programlar olduğunu ileri sürdü. Bunlar aslında metaprogramlardır, ancak yine, tüm metaprogramların bir alt kümesidirler. Fourier Transform West hızlı (FFTW) kütüphane bir metaprogram bir örneğidir. Kaynak kodu çoğunlukla yazılır OCaml ve yüksek performans oluşturmak için birleştirilir C kodu (denilen codelets) bitlerini üretir , Fourier Transform Hızlı belirli makineler için optimize rutinleri. Bu kütüphane aslında Matlab'da FFT rutinlerini sağlamak için kullanılır. FORTRAN'ın ilk günlerinden beri insanlar onlarca yıldır sayısal yöntemler üretmek için programlar yazıyorlar .

Metaprogramlama için desteği entegre eden ilk programlama dili 1950'lerin sonlarında LISt Processor (LISP) diliydi. LISP 1.5 , metaprogramlamayı kolaylaştıran bir dizi özellik içeriyordu. İlk olarak, LISP'nin çekirdek veri türü yuvalanmış listelerdir, yani benzeri ağaçlar, yani (a (b c) d)herhangi bir LISP kodunun bir veri yapısı olarak yerel olarak ifade edilebileceği anlamına gelir. Bu, homoikonisite olarak bilinir. İkinci olarak, LISP kodu QUOTE kullanılarak kolaylıkla veriye dönüştürülebilir. Örneğin (+ 1 2 3)1 + 2 + 3 ekler ve (QUOTE (+ 1 2 3))değerlendirildiğinde 1 + 2 + 3 ekleyen bir ifade oluşturur. Üçüncüsü, LISP, çalışma zamanında üretilen LISP kodu dahil olmak üzere çalışma zamanında LISP kodunu değerlendirmek için ana bilgisayar yorumlayıcısını veya derleyiciyi kullanmanıza izin veren bir meta-döngüsel değerlendirici sağladı. LISP'nin soyundan gelenler arasında Scheme ve Clojure bulunur. Tüm bu dillerde, metaprogramlama en yaygın olarak, tipik olarak makrolar kullanarak kendilerini değiştiren programlar biçiminde görülür.

1970'li yıllarda, Robin Milner gelişmiş Üstdil içeren programlama dilleri arasında ML ailesine dönüştü ki (ML) Standart ML ve OCaml ve kuvvetle etkilemiş Haskell ve F # . Bu diller, diğer dilleri ifade etmeyi kolaylaştırır. Bu dillerde metaprogramlar en yaygın olarak lexer, ayrıştırıcı, yorumlayıcı ve derleyici biçiminde görülür.

1994 yılında Erwin Unruh, C ++ şablon sisteminin Turing'in tamamlandığını ve derleme zamanında rastgele programları çalıştırmak için kullanılabileceğini keşfetti . C ++ şablonu metaprogramlama, (ab) Blitz ++ kitaplığında sayısal yöntemler oluşturmak da dahil olmak üzere birçok farklı şey için kullanan yıkanmamış kitlelere meta programlamayı getirdi .


33

Metaprogramlama sadece programlamadır, ancak temelde "kodu yazan kod yazmaktır" .

Bir program kendi yapısını ve davranışını gözlemleyip değiştirebildiğinde bahsettiğiniz yeteneğe yansıma denir ve bu bir tür metaprogramlama türüdür.

Dinamik olarak yazılmış diller, bu dillerin yorumlanmış doğası ile mümkün kılınan güçlü çalışma zamanı yansıtma özelliklerine sahiptir ...

Statik yazılan diller ayrıca güçlü meta programlama tekniklerine de sahiptir, örneğin C ++ şablonu meta programlama ...


14

Bu sadece benim kişisel görüşüm ve muhtemelen meta programlamanın en liberal tanımıdır.

Bence şunları içerir:

  1. Kod oluşturmayı veya Çalışma zamanı kodu oluşturmayı (veya her ikisini birden) derleyin
  2. Boyut Odaklı Düşünme veya Boyut Odaklı Programlama
  3. Kuru Düşünme

Sanırım bunlardan herhangi birini kullanarak ve kombinasyon halinde oraya gidebilirsiniz:

  1. yansıma
  2. DSL'ler (Etki Alanına Özgü Diller)
  3. Nitelikler (.NET) veya Ek Açıklamalar (Java)
  4. Jenerikler (.NET / Java)
  5. Şablonlar (C ++)
  6. method_missing (Ruby)
  7. kapatmalar / birinci sınıf işlevler / delegeler
  8. AOP - Görünüşe Yönelik Programlama

çok özlü ve düşünceli cevap. bana araştırmam için iyi bir şeyler menüsü verdi. teşekkür ederim!
swyx

6

Metaprogramlama, başka bir programı çıkaran bir program yazmaktır. Bu Lisp gibi dillerin gerçekten iyi olduğu bir şey. Ruby, Lisp, Scheme, vb. Gibi gerçek makroları (C ++ makrolarını değil, çıktıkları kodu değiştirebilenleri) destekleyen bir dilde yapmak, Java gibi bir dilde yapmaktan çok daha kolaydır.

Bir uygulama, belirli bir görevi başarmak için bir programlama dilini geliştirmenin bir yolu olan "alana özgü bir dil" oluşturmaktır. Doğru yapılırsa inanılmaz derecede güçlü olabilir. Ruby on Rails, bu tür programlamanın güzel bir örneğidir.

Bu yöntemi keşfetmekle ilgileniyorsanız , konuyu kapsayan ufuk açıcı kitaplardan biri olan Bilgisayar Programlarının Yapısı ve Yorumlanması'na göz atın.


5

Metaprogramlama, diğer programları (veya kendilerini) verileri olarak yazan veya değiştiren veya çalışma zamanında, aksi takdirde derleme zamanında yapılacak olan işin bir bölümünü yapan bilgisayar programlarının yazılmasıdır. Çoğu durumda bu, programcıların tüm kodu manuel olarak yazmak için harcadıkları süre içinde daha fazla iş yapmalarına olanak tanır veya programlara yeni durumları yeniden derleme olmadan verimli bir şekilde ele almak için daha fazla esneklik sağlar. ( Kaynak .)

Temel olarak, bir hedefe ulaşmak için çalıştırılan daha fazla kod üreten kod yazmaktır. Bu genellikle ya aynı dilde (bir javascript dizesi oluşturmak için javascript kullanarak, sonra evalonu kullanarak) ya da başka bir dil yayınlayarak (bir Windows toplu iş dosyası oluşturmak için .NET kullanarak) yapılır.


4

wikipedia'da konu hakkında güzel bir makale var. Bir şeyin metaprogramlama olarak nitelendirilmesi için çalışma zamanı değişiklikleri yapmak zorunda değilsiniz. Örneğin, birçok kişi derleme zamanında meta programlama yapmak için C ++ şablonlarını kullanır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.