OK, I understand why you might want to do that. But there's nothing domain specific about that. I might want a decent looping construct in any domain. That's just trying to make a decent language, not a domain specific one.
Or is the idea that, as soon as I go beyond the Common Lisp standard, it's "domain specific", no matter how completely general my extensions are?
I've always interpreted DSL as creating a way to write programs in the language of the problem to be solved. A loop construct, no matter how useful, seems to fall short of that.
The for loop example was just to illustrate the difference between function and macro, a complete DSL would be something like making prolog within a Lisp or other examples in racket [1], or for example a special configuration file for electric circuits within the language, or a SQL like interface for manipulating data (you can write LINQ using macros).
It's not a direct comparison of course (nor it is a Lisp), but here is an example of linear optimization in a library that uses macros to make it a DSL closer to the description (in Julia @ before a name means it's macro, so it's easy to see) and one that uses methods:
If in the Julia example they if @variable was a function, then x >= 0 would have been evaluated immediately and it would fail since x was not defined (and if it was x >= 0 would return a boolean). To emulate that you'd probably have to pass a string "x >= 0", which the function would then have to parse (it would be a DSL as well, but one you're writing from scratch), the difference here is that you can just use the language parser directly and compile already with the result.
Or is the idea that, as soon as I go beyond the Common Lisp standard, it's "domain specific", no matter how completely general my extensions are?
I've always interpreted DSL as creating a way to write programs in the language of the problem to be solved. A loop construct, no matter how useful, seems to fall short of that.