La distinción es difícil de hacer y depende del lenguaje utilizado. También es subjetivo.
En clojure, puede definir API que se parecen a un DSL. Por ejemplo, el hipo le permite generar html:
(html [:span {:class "foo"} "bar"])
Esto puede considerarse como un DSL con una sintaxis de lisp. El hecho de que html
podría ser una macro le da la misma cantidad de poder que si estuviera escribiendo una biblioteca html con plantillas de expresiones s (vea sxml )
En python, la misma API puede verse así:
html(["span", {"class" : "foo"}, "bar"])
HTML es una función. Su argumento se evaluará primero y luego se realizará la llamada a la función. El hecho de que la sintaxis de Python sea más específica y la semántica de Python sea más estricta significa que esta expresión es más difícil de interpretar como un DSL independiente del lenguaje.
Una representación de lenguaje clásico es un árbol como la estructura de datos y una función eval llamada recursivamente en sus nodos. Los lenguajes LISP hacen que esta estructura de árbol sea muy evidente, por lo que cualquier llamada de función anidada no se puede distinguir de una función de lenguaje incorporada. Es por eso que la comunidad LISP habla sobre DSL para casi todo.
Creo que la programación se trata de proporcionar abstracciones útiles. Me parece que mirar todo lo que construyes (una biblioteca o incluso la interfaz de usuario de tu aplicación) como elementos del lenguaje que ayudan a las personas a resolver un problema complejo es una forma efectiva de diseñar la mayoría de las cosas. Con esta perspectiva, afirmo que todas las bibliotecas son DSL, pero algunas de ellas están mal diseñadas :-)