Menurut artikel ini , baris kode Lisp berikut mencetak "Hello world" ke output standar.
(format t "hello, world")
Lisp, yang merupakan bahasa homoikonik , dapat memperlakukan kode sebagai data dengan cara ini:
Sekarang bayangkan kita menulis makro berikut:
(defmacro backwards (expr) (reverse expr))
mundur adalah nama makro, yang mengambil ekspresi (direpresentasikan sebagai daftar), dan membalikkannya. Inilah "Halo, dunia" lagi, kali ini menggunakan makro:
(backwards ("hello, world" t format))
Ketika kompiler Lisp melihat baris kode itu, ia melihat atom pertama dalam daftar (
backwards
), dan pemberitahuan bahwa itu menamai makro. Ini melewati daftar yang tidak dievaluasi("hello, world" t format)
ke makro, yang mengatur ulang daftar(format t "hello, world")
. Daftar yang dihasilkan menggantikan ekspresi makro, dan itulah yang akan dievaluasi saat dijalankan. Lingkungan Lisp akan melihat bahwa atom pertamanya (format
) adalah fungsi, dan mengevaluasinya, meneruskannya dengan argumen lainnya.
Dalam Lisp mencapai tugas ini mudah (koreksi saya jika saya salah) karena kode diimplementasikan sebagai daftar ( s-ekspresi ?).
Sekarang lihat cuplikan OCaml ini (yang bukan bahasa homoikonik):
let print () =
let message = "Hello world" in
print_endline message
;;
Bayangkan Anda ingin menambahkan homoiconicity ke OCaml, yang menggunakan sintaks yang jauh lebih kompleks dibandingkan dengan Lisp. Bagaimana Anda akan melakukannya? Apakah bahasa tersebut harus memiliki sintaksis yang sangat mudah untuk mencapai homoiconicity?
EDIT : dari topik ini saya menemukan cara lain untuk mencapai homoiconicity yang berbeda dari Lisp: yang diterapkan dalam bahasa io . Mungkin sebagian menjawab pertanyaan ini.
Di sini, mari kita mulai dengan blok sederhana:
Io> plus := block(a, b, a + b) ==> method(a, b, a + b ) Io> plus call(2, 3) ==> 5
Oke, jadi bloknya berfungsi. Blok plus menambahkan dua angka.
Sekarang mari kita lakukan introspeksi pada anak kecil ini.
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 ==> +
Cetakan dingin suci panas. Anda tidak hanya bisa mendapatkan nama-nama params blok. Dan Anda tidak hanya dapat memperoleh string dari kode sumber lengkap blok. Anda dapat menyelinap masuk ke kode dan menelusuri pesan di dalamnya. Dan yang paling menakjubkan: sangat mudah dan alami. Sesuai dengan pencarian Io. Cermin Ruby tidak bisa melihat semua itu.
Tapi, whoa whoa, hei sekarang, jangan menyentuh tombol itu.
Io> plus message next setName("-") ==> -(b) Io> plus ==> method(a, b, a - b ) Io> plus call(2, 3) ==> -1