Bu makaleye göre , aşağıdaki Lisp kodu satırı "Merhaba dünya" yı standart çıktıya yazdırır.
(format t "hello, world")
Homikonik bir dil olan Lisp, kodu veri olarak şu şekilde ele alabilir:
Şimdi aşağıdaki makroyu yazdığımızı hayal edin:
(defmacro backwards (expr) (reverse expr))
geriye doğru, bir ifadeyi (liste olarak temsil edilir) alan ve tersine çeviren makronun adıdır. İşte yine "Merhaba, dünya", bu sefer makroyu kullanarak:
(backwards ("hello, world" t format))
Lisp derleyicisi bu kod satırını gördüğünde, listedeki (
backwards
) ilk atoma bakar ve makro adını verdiğini fark eder. Değerlendirilmemiş listeyi listeye("hello, world" t format)
yeniden düzenleyen makroya geçirir(format t "hello, world")
. Sonuçta ortaya çıkan liste makro ifadesinin yerini alır ve çalışma zamanında değerlendirilecek olan budur. Lisp ortamı, ilk atomunun (format
) bir işlev olduğunu görecek ve onu değerlendirecek ve argümanların geri kalanını geçirecektir .
Lisp'te bu görevi gerçekleştirmek kolaydır (eğer yanlışsam beni düzelt) çünkü kod liste ( s-ifadeleri ?) Olarak uygulanır.
Şimdi bu OCaml (homoikonik bir dil değildir) snippet'ine bir göz atın:
let print () =
let message = "Hello world" in
print_endline message
;;
Lisp ile karşılaştırıldığında çok daha karmaşık bir sözdizimi kullanan OCaml'a homoiklik eklemek istediğinizi düşünün. Bunu nasıl yaptın? Homikoniklik sağlamak için dilin özellikle kolay bir sözdizimine sahip olması gerekir mi?
DÜZENLEME : Bu konudan Lisp'lerden farklı bir homoiklik elde etmenin başka bir yolunu buldum : io dilinde uygulanan . Bu soruya kısmen cevap verebilir.
Burada basit bir blokla başlayalım:
Io> plus := block(a, b, a + b) ==> method(a, b, a + b ) Io> plus call(2, 3) ==> 5
Tamam, blok çalışıyor. Artı bloğu iki sayı ekledi.
Şimdi bu küçük adama biraz içgözlem yapalım.
Io> plus argumentNames ==> list("a", "b") Io> plus code ==> block(a, b, a +(b)) Io> plus message name ==> a Io> plus message next ==> +(b) Io> plus message next name ==> +
Sıcak kutsal soğuk kalıp. Sadece blok parametrelerinin isimlerini elde etmekle kalmaz. Ve sadece bloğun tam kaynak kodunun bir dizesini elde etmekle kalmaz. Koda gizlice girip içindeki mesajları değiştirebilirsiniz. Ve en şaşırtıcısı: çok kolay ve doğal. Io'nun arayışına sadık. Ruby'nin aynası bunların hiçbirini göremiyor.
Ama, whoa whoa, hey şimdi, o kadrana dokunma.
Io> plus message next setName("-") ==> -(b) Io> plus ==> method(a, b, a - b ) Io> plus call(2, 3) ==> -1