You can write macros (as well as functions, actually) that accept AST and emit transformed AST back. It has quote and unquote. Turns out that it doesn't need homoiconicity to accomplish Lisp-level macro capability, which means it has all the power of a Lisp but with actual syntax (which is, like it or not, more appealing to many people) in a language with deep pattern-matching and completely immutable data guarantees.