Згідно з цією статтею, наступний рядок коду Lisp друкує "Hello world" на стандартний вихід.
(format t "hello, world")
Lisp, що є гомоніконімічною мовою , може розглядати код як дані таким чином:
А тепер уявіть, що ми написали такий макрос:
(defmacro backwards (expr) (reverse expr))
назад - це назва макросу, який приймає вираз (представлений у вигляді списку) і повертає його назад. Ось знову "Привіт, світ", на цей раз за допомогою макросу:
(backwards ("hello, world" t format))
Коли компілятор Lisp бачить цей рядок коду, він переглядає перший атом у списку (
backwards
) і помічає, що він називає макрос. Він передає неоцінений список("hello, world" t format)
макросу, який переставляє список у(format t "hello, world")
. Отриманий список замінює вираз макросу, і саме це буде оцінено під час виконання. Середовище Лісп побачить, що його перший атом (format
) є функцією, і оцінить його, передавши йому решту аргументів.
У Lisp досягти цього завдання досить просто (виправте мене, якщо я помиляюся), оскільки код реалізований як список ( s-вирази ?).
Тепер погляньте на цей фрагмент OCaml (який не є гомоніконічною мовою):
let print () =
let message = "Hello world" in
print_endline message
;;
Уявіть, що ви хочете додати гомонікості OCaml, який використовує набагато складніший синтаксис порівняно з Lisp. Як би ти це зробив? Чи має мова володіти особливо легким синтаксисом для досягнення гомонікості?
EDIT : з цієї теми я знайшов інший спосіб досягти гомоконічності, який відрізняється від Lisp: той, що реалізований мовою io . Це може частково відповісти на це питання.
Тут почнемо з простого блоку:
Io> plus := block(a, b, a + b) ==> method(a, b, a + b ) Io> plus call(2, 3) ==> 5
Гаразд, тому блок працює. Блок плюс додав два числа.
Тепер давайте зробимо трохи самоаналізу цього маленького хлопця.
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 ==> +
Гаряча свята холодна цвіль. Мало того, що ви можете отримати імена блок-парам. І не тільки ви можете отримати рядок повного вихідного коду блоку. Ви можете прокрастись до коду та пересувати повідомлення всередині. І найдивовижніше з усіх: це жахливо просто і природно. Вірно шукає Іо. Дзеркало Рубі нічого з цього не бачить.
Але, чекайте, ей зараз, не торкайся цього циферблата.
Io> plus message next setName("-") ==> -(b) Io> plus ==> method(a, b, a - b ) Io> plus call(2, 3) ==> -1