What's really sad is that not having overloading "ON" by default is a good idea, but it doesn't mean that language has to stop there, it's really simple to have a small language feature which would say that
a #everything_until_the_next_space b is rewritten in #everything_until_the_next_space(a,b)
So you'd have:
-a #foo b #foo c is foo(foo(a,b),c)
-a #foo b #bar c is forbidden, use parenthesis.
-and maybe #: for the inverse composition where
a #:foo b #:foo c is foo(a, foo(b,c))
It's explicit, no hidden overloading, yet it's "short" enough to be usable: (a #* b) #+ c isn't that much worse than a*b+c and is much more readable than madd(mmul(a,b),c)..
If there is no implicit conversion name clashes shouldn't be too bad (both #+ could be usable for matrix and for graphic libraries).