2011-09-03 16 views
7

¿Alguien sabe cómo implementar method_missing (à la Ruby) en Clojure? P. ej.Método Clojure Falta

(defn method_missing [name & args] 
    (foo name args)) 

Sería muy útil para una DSL, si se usa correctamente.

¡Gracias de antemano!

+2

¿En qué casos desea que se invoque esta función? – Brian

Respuesta

10

En Ruby, method_missing es uno de los constructos primarios para la metaprogramación. Está estrechamente vinculado a la estructura orientada a objetos de Ruby, creando dinámicamente métodos en una clase a partir de "metaclases". Esto se puede hacer porque en Ruby las clases también son objetos.

Dado que Clojure es un lenguaje funcional, imitar este rubyismo tiene poco sentido. Sin embargo, una de las expresiones idiomáticas básicas de Lisps (como Clojure) es que el código es información: y como el código puede generar datos, también puede generar código. La forma principal de hacer esta metaprogramación en Lisp es macros.

Le sugiero que lea más sobre las macros y lo que pueden y no deben hacer. Tenga en cuenta que, al igual que en Ruby, el código generado dinámicamente es generalmente más difícil de depurar y mantener. A menudo, el uso inteligente de otros modismos funcionales puede ser una mejor solución estructural.

+3

Estoy de acuerdo con la mayoría de esto, pero me opongo a la afirmación de que el código generado dinámicamente es difícil de depurar o mantener. Las macros son una gran ayuda para la simplificación y el mantenimiento, siempre que se utilicen con buen gusto. – amalloy

+0

Solo quería señalar cuándo usar las macros debe considerarse cuidadosamente, y cuando puede hacer algo con funciones normales, esto debería ser preferido. – NielsK

+1

Al haber venido de Ruby, descubrí que puede tomar un tiempo comprender el poder de la composición de funciones. Usar macros para evitar esto puede ser contraproducente. – NielsK

5

Puede crear una macro que envuelva las llamadas a funciones en un bloque try-catch que atrape este tipo de excepción.

p. Ej. Algo así como

(with-default-method [fxn args default] ...) 

se expandiría para

(try (fxn args) (catch java.lang.IllegalArgumentException _) (finally default)) 

Lo anterior es en su mayoría a mano agitar, porque no creo que esto es una buena idea en absoluto: es el abuso del sistema de excepciones y Creo que hará cosas inesperadas.

No soy una persona de Ruby, pero tengo la sensación de que esta característica está integrada en ese idioma; en java, y por extensión, clojure, tendrías que tratar de pasarlo, y no sería lindo.