I developed a fear of macros after realizing that they're not first-class, and you can't pass macros to functions as arguments for instance (instead you need to wrap them up in function, which doesn't work well with variadic forms).
An even more useful concept exists in J.Shutt's Kernel programming language[1] - that of first class operatives. Every entity becomes a first-class object, which can be an operative (like some special forms) or an applicative (a scheme function). operatives do not implicitly evaluate the operands, so you can easily create macro-like behavior by defining your own evaluation model. It's also trivial to convert between applicatives and operatives with wrap and unwrap (which are not special forms, they're defined in terms of vau and eval).
It turns out that fexprs, which is what Kernel provides, are widely considered a bad idea in the Lisp community, and were abandoned in favor of macros for a reason. The basic problem is that you can never tell whether your function call is really a function call or a macro application, until you run the program, and therefore you can't reason about your code at all. Incidentally, this also means that your compiler can't reason about your code, and thus optimization is basically impossible.
The fexprs provided by Kernel are not the same as the ones in traditional lisps which were abandoned - Shutt has developed a theory for reasoning about them in some ways (the vau-calculus, which is capable of defining the lambda calculus too). He describes pure and impure versions of the vau calculus in his dissertation.
Firstly, operatives are improved over the traditional ones by having lexical scoping - where the original lisps were dynamically scoped. The other main feature of operatives is that they gain access to the dynamic scope from where they were called - as this environment is passed implicitly to the operative when it is evaluated.
You're right that they do not allow us to reason inductively about code in the same way as the lambda calculus due to this, but it's a trade off for incredible flexibility. I think we can build alternative models to reason about them for purposes of optimisation and such. (Or alternatively, one can have operatives behave as compilers - in which you feed in type-tagged expressions, and your compiler-operatives can perform full type checking - then output an applicative which strips this type information). I see the possibilities as endless, because the model is extremely abstract.
Kernel choses not to enforce the static separation of operatives and applicatives for simplcity - instead, a convention based approach is used whereby operatives are prefixed with "$", (such as $vau, $lambda, $define!, $provide!). One can check them during runtime with the operative? and applicative? predicates too.
However, it would be perfectly possible to create a compiler which can know this difference, since the forms `($define! ($vau ...))` and `($define! ($lambda ...))` which distinguish them could be given special forms or special syntax in an alternative representation of this model, although you would not be able to tell whether an applicative uses some operatives internally - that's the idea of encapsulation - implementation information is meant to be hidden. (Even at the cost of performance, which often doesn't matter.)
Even if Kernel is not as widely practical as lambda-calculus based languages - Shutt's dissertation is definitely worth a read, and shouldn't be discarded because of a perception of bad fexprs from 40 years ago.
An even more useful concept exists in J.Shutt's Kernel programming language[1] - that of first class operatives. Every entity becomes a first-class object, which can be an operative (like some special forms) or an applicative (a scheme function). operatives do not implicitly evaluate the operands, so you can easily create macro-like behavior by defining your own evaluation model. It's also trivial to convert between applicatives and operatives with wrap and unwrap (which are not special forms, they're defined in terms of vau and eval).
[1]:http://web.cs.wpi.edu/~jshutt/kernel.html