Prefiero que los ejemplos estén en una variante de Lisp (puntos de bonificación para Clojure o Scheme) ya que eso es con lo que estoy más familiarizado, pero cualquier comentario sobre DBC en lanzas funcionales sería por supuesto valioso para la comunidad en general.¿Cómo podría implementar el diseño por contrato en Clojure específicamente o en los lenguajes funcionales en general?
Aquí es una forma obvia:
(defn foo [action options]
(when-not (#{"go-forward" "go-backward" "turn-right" "turn-left"} action)
(throw (IllegalArgumentException.
"unknown action")))
(when-not (and (:speed options) (> (:speed options) 0))
(throw (IllegalArgumentException.
"invalid speed")))
; finally we get to the meat of the logic)
Lo que no me gusta de esta aplicación es que la lógica de contrato oscurece la funcionalidad del núcleo; el verdadero propósito de la función se pierde en las verificaciones condicionales. Este es el mismo problema que planteé en this question. En un lenguaje imperativo como Java, puedo usar anotaciones o metadatos/atributos integrados en la documentación para sacar el contrato de la implementación del método.
¿Alguien ha tratado de agregar contratos a los metadatos en Clojure? ¿Cómo se usarían las funciones de orden superior? ¿Qué otras opciones hay?
¿Ha visto cómo se implementan en los contratos PLT-esquema? Echar un vistazo. http://docs.plt-scheme.org/guide/contracts.html –
@Alexey - ¡Es un recurso espectacular! Soy bastante nuevo para Scheme (trabajando a través de los libros The Little/Seasoned) y no sabía que esto existía, así que gracias. – rcampbell
No es una respuesta directa a su pregunta, pero eche un vistazo a QuickCheck y sus derivados (ClojureCheck). Básicamente se trata de pruebas basadas en propiedades, y en los contratos se definen propiedades para que pueda obtener fácilmente las pruebas generadas también. – Masse