Bir çeşit meta programlamaya izin veren birçok dil var . Özellikle, Lisp dil ailesi hakkında konuşacak bir cevap görünmediğine şaşırdım .
Wikipedia'dan:
Metaprogramming, programları kendi verileri olarak ele alma becerisine sahip bilgisayar programları yazmaktır.
Metinde daha sonra:
Lisp muhtemelen hem tarihsel önceliği hem de metaprogramlamanın basitliği ve gücünden dolayı metaprogramlama olanaklarına sahip olan en iyi dildir.
Lisp dilleri
Lisp’e hızlı bir şekilde giriş yapılır.
Kodu görmenin bir yolu bir talimat paketidir: bunu yapın, sonra yapın, sonra başka bir şey yapın ... Bu bir liste! Programın yapması gerekenlerin bir listesi. Ve tabii ki döngüler ve benzerlerini temsil etmek için listelerde listeler olabilir.
Biz a, b, c, d böyle unsurları içeren bir liste temsil ederse: (abcd) bir şeyler almak bir Lisp işlev çağrısında gibi görünüyor a
fonksiyonudur ve b
, c
, d
bağımsız değişkendir. Gerçekte tipik "Merhaba Dünya!" program şöyle yazılabilir:(println "Hello World!")
Tabii ki b
, c
ya d
yanı şey değerlendirmek listeleri olabilir. Aşağıdaki: (println "I can add :" (+ 1 3) )
sonra "" ekleyebilirim: 4 "yazdıracaktı.
Dolayısıyla, program iç içe geçmiş listelerin bir dizisidir ve ilk öğe bir işlevdir. İyi haber şu ki listeleri değiştirebiliriz! Böylece programlama dillerini değiştirebiliriz.
Lisp avantajı
Lisps, programlama dilleri yapmak için bir araç takımı kadar programlama dili değildir. Programlanabilir bir programlama dili.
Bu, Lisps'ta yeni operatörler yapmak için çok daha kolay değil, bazı operatörleri başka dillerde yazmak da neredeyse imkansız, çünkü fonksiyona geçildiğinde argümanlar değerlendiriliyor.
Örneğin, C benzeri bir dilde diyelim ki if
kendinize bir operatör yazmak isteyin ,
my-if(condition, if-true, if-false)
my-if(false, print("I should not be printed"), print("I should be printed"))
Bu durumda, her iki argüman, argümanların değerlendirme sırasına bağlı bir sırada değerlendirilecek ve yazdırılacaktır.
Lisps'ta bir operatör yazmak (buna makro diyoruz) ve bir fonksiyon yazmak aynı şeyle ilgili ve aynı şekilde kullanılıyor. Makro için bu parametreleri olmak önemli fark edilir değil makro argümanlar olarak iletilen önce değerlendirilir. if
Yukarıdaki gibi bazı operatörleri yazabilmek için bu şarttır .
Gerçek dünya dilleri
Burada tam olarak ne kadar kapsam dışında olduğunu gösteriyorum, ancak daha fazla bilgi edinmek için bir Lisp'te programlama yapmayı denemenizi tavsiye ediyorum. Mesela şuna bir bakabilirsiniz:
- Şema , küçük çekirdekli yaşlı, oldukça "saf" bir Lisp
- Common Lisp, iyi entegre bir nesne sistemine sahip daha büyük bir Lisp ve birçok uygulama (ANSI standardizedir)
- Yazılı bir Lisp raketi
- En sevdiğim Clojure , yukarıdaki örnekler Clojure koduydu. JVM'de çalışan modern bir Lisp. Orada üzerinde Clojure makro bazı örnekler SO yanı (ancak bu başlamak için doğru yer değil. Ben bakardım 4clojure , braveclojure veya Clojure koans ilk başta)).
Oh ve bu arada, Lisp LISt İşleme anlamına geliyor.
Örneklerinizle ilgili olarak
Aşağıdaki Clojure kullanarak örnekler vereceğim:
Bir yazabilirsiniz Eğer add
Clojure işlevi (defn add [a b] ...your-implementation-here... )
, bunu adlandırabilirsiniz +
öylesine gibi (defn + [a b] ...your-implementation-here... )
. Aslında, gerçek uygulamada yapılan şey budur (işlevin gövdesi biraz daha fazladır, ancak tanım aslında yukarıda yazdığımla aynıdır).
Peki ya ek gösterimi? Clojure bir prefix
(veya Lehçe) gösterimi kullanır, bu yüzden infix-to-prefix
öneki kodu Clojure koduna dönüştürecek bir makro yapabiliriz . Bu aslında şaşırtıcı derecede kolay (aslında clojure koanlarındaki makro egzersizlerden biri)! Ayrıca vahşi doğada da görülebilir, örneğin bkz. Incanter $=
makrosu .
İşte anlatılan koanların en basit hali:
(defmacro infix [form]
(list (second form) (first form) (nth form 2)))
;; takes a form (ie. some code) as parameter
;; and returns a list (ie. some other code)
;; where the first element is the second element from the original form
;; and the second element is the first element from the original form
;; and the third element is the third element from the original form (indexes start at 0)
;; example :
;; (infix (9 + 1))
;; will become (+ 9 1) which is valid Clojure code and will be executed to give 10 as a result
Noktayı daha da ileri götürmek için bazı Lisp alıntıları :
“Lisp'i farklı kılan şeyin bir kısmı, gelişmek üzere tasarlanmış olmasıdır. Lisp'i yeni Lisp operatörleri tanımlamak için kullanabilirsiniz. Yeni soyutlamalar popüler hale geldiğinde (örneğin, nesne yönelimli programlama), bunları Lisp'te uygulamak her zaman kolay olur. DNA gibi, böyle bir dilin de tarzı yok. ”
- Paul Graham, ANSI Ortak Lisp
“Lisp'te programlama, evrenin ilkel güçleriyle oynamak gibidir. Parmak uçlarınız arasında yıldırım gibi geliyor. Başka hiçbir dil bile yakın hissetmiyor. ”
- Glenn Ehrlich, Lisp'e Giden Yol