[racket] Definition of DSL?

From: Sean Kanaley (skanaley at gmail.com)
Date: Mon Jun 24 15:53:42 EDT 2013

As said in SICP, "eval" is the ultimate language interpreter, capable of 
implementing anything computable.  You could feed it code (a language) 
to interpret C code (the DSL to interpret C, so this code in turn takes 
a parameter of the C to interpret just as eval takes a parameter of the 
Scheme to interpret).  Now in effect, by running (eval (eval-c 
<bunch-of-c-code>)), eval interprets C! But does the thing fed to eval 
have to be an eval-er of a pre-existing "main language" to qualify as an 
interpreter for a DSL?  How complex must the input to the 
sub-interpreter be to breach into DSL territory?  I believe there is no 
minimum, and therefore every function is part of some DSL:

(define (eval-q l)
   (for-each displayln l))

The Q language, unlike C, is very simple.  The grammar is any Scheme 
list, which it interprets by printing elements into newlines. "eval-q" 
makes "eval" now instead eval Q:

 > (eval '(list 1 2 3))
'(1 2 3)

 > (eval '(eval-q (list 1 2 3)))
1
2
3

The fact that eval-q falls short of implementing C to me does not make 
it a non-DSL.  Its domain just happens to be limited to printing 
elements of a list.  In other words, why are the following different:

(eval '(eval-q '(1 2 3)))

(eval '(eval-c "int main() { return 0; }"))

If the answer is that eval-c must have a more difficult implementation, 
I don't believe that's the essence of a DSL!

An example of a more powerful DSL though that similarly does not rely on 
macros or requiring different input syntax is the picture language from 
SICP, or any of the languages from the Haskell School of Expression.

The best way to program is to solve the problem in a language perfect 
for solving the problem.  Otherwise, the program is written 
inefficiently relative to this better language.  To this end, every new 
definition (abstraction) must either bolster the language towards 
solving the problem directly, or, once at this level, solve the problem 
directly.  Every abstraction defined that is not an immediate "solution 
node" can then be considered part of DSL for that solution.

Posted on the users mailing list.