La distinzione è difficile da fare e dipende dal linguaggio usato. È anche soggettivo.
In clojure, puoi definire API che assomigliano a un DSL. Ad esempio, hiccup consente di generare html:
(html [:span {:class "foo"} "bar"])
Questo può essere considerato come un DSL con una sintassi Lisp. Il fatto che html
possa essere una macro gli dà lo stesso potere di se stessi se si stesse scrivendo una lib di template html con espressioni s (si veda sxml )
In python, la stessa API può essere simile a:
html(["span", {"class" : "foo"}, "bar"])
html è una funzione. Il suo argomento verrà valutato per primo e quindi la chiamata alla funzione avverrà. Il fatto che la sintassi python sia più specifica e la semantica python sia più severa significa che questa espressione è più difficile da interpretare come DSL indipendentemente dalla lingua.
Una rappresentazione linguistica classica è una struttura ad albero come i dati e una funzione eval chiamata ricorsivamente sui suoi nodi. I linguaggi LISP rendono questa struttura ad albero molto evidente, quindi qualsiasi chiamata di funzione annidata è indistinguibile da una funzione di linguaggio incorporata. Ecco perché la comunità LISP parla di DSL per quasi tutto.
Credo che la programmazione stia fornendo utili astrazioni. Trovo che esaminare tutto ciò che costruisci (una lib o anche l'interfaccia utente della tua applicazione) come elementi linguistici che aiutano le persone a risolvere un problema complesso è un modo efficace per progettare la maggior parte delle cose. Con questa prospettiva, asserisco che tutte le librerie sono DSL, ma alcune sono mal progettate: -)