No, but it&#x27;s also not a homoiconic language, and it supports syntactic macros just fine.  Homoiconicity might make procedural macros convenient, but it&#x27;s far from a requirement.  And then pattern-template macros are just as convenient in a more &quot;syntactically rich&quot; language as they are in a homoiconic one.<p>See also:  camlp4&#x2F;camlp5.<p>And then there&#x27;s the idea of pattern-match rewriting systems.  iirc, GHC has something like that to rewrite certain expressions as optimizations, like:<p><pre><code>    (map f) . (map g)  =&gt;  map (f . g)
</code></pre>
In a pure language, the two expressions are equivalent, but the latter is more efficient because it traverses the list only once rather than twice.<p>The Cat programming language had a similar sort of &quot;macro&quot; system, but its web site seems to have disappeared.  Shame, it was a really neat little concatenative language.<p>Homoiconicity is certainly neat, but it&#x27;s not about macros at all.  It&#x27;s about having a Lisp-style `read` function.  That&#x27;s it.<p>Also, Dylan&#x27;s syntax wasn&#x27;t based on M-expressions <i>per se</i>, at least not in the &quot;classical&quot; LISP 1.5 sense of the term.  It was just an Algolesque syntax rather than a façade layered above S-expressions.  If you can claim that Dylan was based on M-expressions, then you could just as truthfully claim that Lua, Ruby, JavaScript, etc. are based on M-expressions.  I won&#x27;t say that it&#x27;s strictly false, but I don&#x27;t think that&#x27;s quite how most people familiar with M-expressions think of them.