How can you provide a REPL language without analyzing it at runtime?
Write Lua random syntax in the REPL? Not a great improvement over
C++. Not to mention that you'll probably use something like `eval`
which is not compilation thus inferior.
By the way, even your original example - I can't see how it can work
honestly. How can you identify fields through (lambda) parameter names
only (no mention of types either)? Probably the least
boilerplate-heavy solution would be stringly typed.
Well, dynamic queries by end users is the main goal here. Your static
helper functions are completely unusable in that context. Analysing a
query and generating code at runtime is easy and idiomatic with
uniform syntax (and accompanying language support) and the claim is
that solution is not only speedier but implementation in CL is
qualitatively simpler than the alternatives.
It's allegorical in the sense that this is general Lisp technique
useful not just in this case. The DSL is targeted at (non programmer)
end users and supposed to be fired through a REPL. Wouldn't want to
make them write C++ with lambdas, semi-columns and whatever syntax
traps of the latest standard.
Implementing a "simple virtual machine" for a particular task is
greenspunning[1]. Introducing a JIT library is work, complexity, debug
and portability issues. LLVM compiles much slower to native code as
the Clasp[2] guys notice comparing to SBCL. And in the end, any of
these would be at most "competitive" to the simple Common Lisp
implementation in speed (which is even portable across the different
implementations).
> The question is whether you want that sort of power in day-to-day programming
It's good to use the least powerful mechanism, no doubt. But it seems you are trying to sneak the usual "macros are too powerful for everyday use" so better be left out of a language altogether? I think when the storm comes - you'd better be equipped. Having varied ways to tackle problems (and macros are sort of linguistic abstraction orthogonal to lambda calculus/Turing machine derived toolboxes) allows for less complex solutions.
"we should always use the least powerful mechanism that will accomplish our goal"
I like this when implementing something for non proficient users. But when it comes to providing tools for (supposedly) advanced users, like programmers... There's late-"socialism" joke in Bulgaria: "thrift is mother of misery". A designer doesn't know ahead of time what problems "creative" users will face long term. Providing a set of simplest mechanisms for today's challenges would possibly constrain them in the future - combination of multiple mechanisms in ways not foreseen may add large incidental complexity (like OO design patterns). Which could be avoided if less by count but more powerful mechanisms were used in first place. Macros have main role in keeping Common Lisp relevant to the latest paradigm hypes despite the standard being set in stone. Opposite to this, for example, C++ must keep introducing piles of new least-powerful mechanisms to keep pace.
So where's Haskell's advanced object system or the restart/condition system that Common Lisp has? Even its performance is hardly on par with CL for all the flexibility of the latter.
I'm yet to see a "modern" (statically-typed) language with random syntax whose macro-like facilities are actually usable by mere mortals. My observation is that in practice lisp programmers, even with the good rule of thumb of not using macros when functions suffice, still use way way more macrology. Good macros are just the opposite of reader burden - they tame complexity.
And (compile-time) macros are one thing, but what happens when you need metaprogramming at runtime (for example dynamic code generation)? With the Common Lisp compiler being always present one can easily generate and compile arbitrary code at any point in time. Here's simple real world example (shameless plug):
Static languages are still complete blubs compared to lisps as far as practical metaprogramming goes. And Common Lisp's type system is much less of a blub in that regard.
By the way, even your original example - I can't see how it can work honestly. How can you identify fields through (lambda) parameter names only (no mention of types either)? Probably the least boilerplate-heavy solution would be stringly typed.