no hay plantillas especiales para DSL - que acaba de tomar herramientas disponibles en el idioma y tratar de hacer que lo más conveniente y cerca del dominio de lo posible. Lisp solo te da más herramientas que otros lenguajes.
Para el ejemplo concreto de buen aspecto DSL en ClojureQL. Inicialmente, SQL se creó como DSL para bases de datos relacionales. Y es muy conveniente para trabajar desde la consola ... pero no desde el lenguaje de programación como Java o Clojure. Java vino con grandes marcos ORM como Hibernate, y Clojure ofrece DSL simple que es tan conveniente como SQL original, pero funciona de forma totalmente como parte de la lengua:
(select (table :users) (where (= :id 5)))
cosa común en Lisp DSL está utilizando construcciones como defsomething
. Por ejemplo, en un libro (lo siento, no recuerdo su nombre) hay un ejemplo de coincidencia de patrones en el texto. El autor crea el módulo con un número de emparejamiento como ?
para una palabra, +
para una o más palabras, *
para cero o más palabras y así sucesivamente. Para este propósito crea macro defmatcher
que requiere cierta sintaxis y agrega controlador para esta sintaxis al registro central. Esto es solo abstracción: en lugar de varias operaciones repetidas, introduce una sola macro que dice lo que realmente quiere hacer: definir el matcher. También este ejemplo usa ambos: macros y funciones de orden superior.
Así que, una vez más, no hay nada especial en las DSL basadas en Lisp: solo describe el área de dominio con las herramientas que tiene en su idioma, ya sea Java, Clojure o cualquier otra cosa. Simplemente acostúmbrate con las instalaciones de idiomas y verás cómo debe ser.
UPD. Algunos ejemplos del "mundo real" donde DSL basado en Lisp son más convenientes que, por ejemplo, programación orientada a objetos:
Dominio: dillership coche
(defcar my-cool-car :wheels 4, :doors 2, :color red) ;; in Java you need Factory
(def car1 (make-car my-cool-car)) ;; and lots of methods to
;; add features to cars and
;; cars to factory
Dominio: sistema de facturación
(transaction ;; in Java you cannot create wrapping constructs
(withdraw account1 100) ;; so you have to use inheritance, annotations, etc.
(put account2 100)) ;; which is much more code
Dominio: algunos servicios web, que manejan solicitudes de varios tipos
(defhandler :show-all (fn [params] ...)) ;; adds defined function to the
(defhandler :find-best (fn [params] ...)) ;; map of :message-type -> function
...
(defn handle [message]
(let [msg-type (:type message), msg-params (:params message)]
(if (contains? *handlers* msg-type)
((*handlers* msg-type) msg-params)
(throw (Exception. (concat "No handler for type" (:type message)))))))
No hay Lo especial de estos ejemplos: puedes implementarlos en Java o en cualquier otro idioma. Sin embargo, cosas como palabras clave (primer ejemplo), funciones de orden superior (segundo ejemplo), macros (los tres ejemplos) hacen que el código sea más conciso y descriptivo.
... lancet es una DSL, pero no es realmente un problema del "mundo real", ya que la mayoría de los programadores nunca han intentado escribir un sistema así: echa un vistazo a la buena aplicación Google: jpetstore .... – jayunit100