http://www.draketo.de/english/wisp#text-table-of-contents
[ed: For Racket, see also: https://github.com/takikawa/sweet-racket ]
[ed2: See also the "readable" package for Common Lisp and for Scheme: https://sourceforge.net/p/readable/wiki/Install-howto/ ]
Your macros will break all over the place in languages that don't have this property.
http://srfi.schemers.org/srfi-110/srfi-110.html#wisp
^1 [ed: well, not "just python syntax", but if you wanted that, you would be better off using python. But python-like syntax/skin is absolutely doable. ]
See also: camlp4/camlp5.
And then there's the idea of pattern-match rewriting systems. iirc, GHC has something like that to rewrite certain expressions as optimizations, like:
(map f) . (map g) => map (f . g)
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.The Cat programming language had a similar sort of "macro" system, but its web site seems to have disappeared. Shame, it was a really neat little concatenative language.
Homoiconicity is certainly neat, but it's not about macros at all. It's about having a Lisp-style `read` function. That's it.
Also, Dylan's syntax wasn't based on M-expressions per se, at least not in the "classical" 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't say that it's strictly false, but I don't think that's quite how most people familiar with M-expressions think of them.
I know, my remark was more into the sense of being based as departure point, not as being a pure M-expression implementation.