According to this article the following line of Lisp code prints Hello world to standard output.(format t hello, world)Lisp, which is a homoiconic language, can treat code as data in this way:Now imagine that we wrote the following macro:(defmacro backwards (expr) (reverse expr))backwards is the name of the macro, which takes an expression  (represented as a list), and reverses it. Heres Hello, world again,  this time using the macro:(backwards (hello, world t format))When the Lisp compiler sees that line of code, it looks at the first  atom in the list (backwards), and notices that it names a macro. It  passes the unevaluated list (hello, world t format) to the macro,  which rearranges the list to (format t hello, world). The resulting  list replaces the macro expression, and it is what will be evaluated  at run-time. The Lisp environment will see that its first atom  (format) is a function, and evaluate it, passing it the rest of the  arguments.In Lisp achieving this task is easy (correct me if I'm wrong) because code is implemented as list (s-expressions?). Now take a look at this OCaml (which is not a homoiconic language) snippet:let print () =    let message = Hello world in    print_endline message;;Imagine you want to add homoiconicity to OCaml, which uses a much more complex syntax compared to Lisp. How would you do that? Does the language has to have a particularly easy syntax to achieve homoiconicity?EDIT: from this topic I found another way to achieve homoiconicity which is different from Lisp's: the one implemented in the io language. It may partially answer this question.Here, lets start with a simple block:Io> plus := block(a, b, a + b)==> method(a, b,         a + b    )Io> plus call(2, 3)==> 5Okay, so the block works. The plus block added two numbers.Now lets do some introspection on this little fellow.Io> plus argumentNames==> list(a, b)Io> plus code==> block(a, b, a +(b))Io> plus message name==> aIo> plus message next==> +(b)Io> plus message next name==> +Hot holy cold mold. Not only can you get the names of the block  params. And not only can you get a string of the blocks complete  source code. You can sneak into the code and traverse the messages  inside. And most amazing of all: its awfully easy and natural. True  to Ios quest. Rubys mirror cant see any of that.But, whoa whoa, hey now, dont touch that dial.Io> plus message next setName(-)==> -(b)Io> plus==> method(a, b,         a - b    )Io> plus call(2, 3)==> -1
How to make a language homoiconic
programming languages;functional programming
You can make any language homoiconic. Essentially you do this by 'mirroring' the language (meaning for any language constructor you add a corresponding representation of that constructor as data, think AST). You also need to add a couple of additional operations like quoting and unquoting. That's more or less it.Lisp had that early on because of its easy syntax, but W. Taha's MetaML family of languages showed that it's possible to do for any language.The whole process is outlined in Modelling homogeneous generative meta-programming. A more lightweight introduction to the same material is here.