Not really. Arc has macros and yet all the syntactic sugar ([], :, ~) is implemented in Scheme. Access to the read-table would be a start.
What I would really like to see though is a requirement for the code walker to be exposed and extendable.
Ah, ok! Now I get your point. Yes, it would be really useful to be able to extend syntax like that. However I believe readtable access should be limited. Let me explain.
I don't mean "limited" as in "dumbed down" but as in "predictable". It's nice to extend syntax, but it's even nicer when your editor can indent and colorize your program without a hitch. You are right: macros don't alter syntax significantly. And that's what makes them so nice: parens are still balanced, editors don't barf and, if you use with-gensyms and once-only, referential transparency is broken only where necessary.
A good place to start, IMHO, would be the ability to define operators: infix (like ':'), suffix ('~'), postfix and "wrapping" (like '[...]'). Operators would satisfy all of Arc's syntax-extension needs (unless I'm missing something). For example:
(operator wrapping #\[ #\] body
`(fn (_) ,@body))
(operator prefix #\~ symbol
`(fn args (not (apply ,symbol args))))
...or something like that.
Simonb: do you think this solution would fill the gap? Can you point out some situation where you would like even more control over the read-table?
The problem with giving only a limited support for something is that people will invariably want more and start to abuse the system. For instance with operators you risk ending up with a slew of little languages full of glyphs rich with semantic meaning (think Perl).
Macros allow you to build "up", to add new [abstraction] layers to your language but sometimes it would be nice to be able to go "down" as well and add new semantics that non-trivially interacts with the host language. Re-entrant continuations or proper tail recursion for CL come to mind. Another example of such friction is Qi [http://www.lambdassociates.org/aboutqi.htm] where all sorts of hacks (case sensitivity etc.) are needed instead of it simply being a library.
Theoretically one could design a language powerful enough that this would never be necessary but even then you would want code-walkers for optimisations. CL with it's compiler macros is a step in the right direction but it soon runs aground when you want to do things such CPS optimisations. Say you want to merge nested map-operations in CL:
(map 'vector #'^2 (map 'vector #'+ a b))
=>
(map (lambda (:g1 :g2) (^2 (+ :g1:g2))) a b)
This is something compiler macros are great for, but as soon as the inner map is wrapped in a function we have a problem. What our compiler macro sees is something like:
(map 'vector #^2 (vector+ a b))
and at that point we have no idea what vector+ looks like.
In terms of a compromise, access to the environment at compile-time would go a long way (CL has provisions for this, but the standard doesn't say anything about how the environment should look like) and maybe a facility to get function definitions (forced inlining if you will).