2008-09-22 14 views
22

C++ es probablemente el lenguaje más popular para static metaprogramming y Java doesn't support it.Idiomas no C++ para programación generativa?

¿Hay otros lenguajes además de C++ que admitan programación generativa (programas que crean programas)?

+1

Me he quejado antes de la moderación de StackOverflow, pero permítanme detenerme aquí, y simplemente señalar una observación ... ¿ven una sobrecarga de "debate, discusiones, sondeos o discusiones extensas" aquí? Si eso es lo que tememos, evaluemos qué tan malo es en las respuestas de esta pregunta. Si, en lugar de un horrendo episodio de Jerry Springer, vemos información inteligente y valiosa compartida respetuosamente y apreciada, entonces quizás deberíamos dejar la pregunta abierta. De lo contrario, nos preocupamos demasiado por problemas que ni siquiera tenemos. –

+4

He editado esta pregunta para eliminar las solicitudes de "mejor". Por favor considere la reapertura. Por cierto: fue a través de las respuestas a esta pregunta que escuché por primera vez de Clojure. Entonces fue constructivo para mí. ¡Gracias a quienes respondieron y comentaron! – jwfearn

Respuesta

32

La alternativa a la metaprogramación de estilo de plantilla es Macro-estilo que se ve en varias implementaciones de Lisp. Sugiero que descargue Paul Graham's On Lisp y también eche un vistazo a Clojure si le interesa un Lisp con macros que se ejecute en la JVM.

Las macros en Lisp son mucho más potentes que el estilo C/C++ y constituyen un lenguaje por derecho propio: están destinadas a la metaprogramación.

+3

Hmm, ¿cómo son las macros Lisp un lenguaje por derecho propio? Es todo Lisp, esa es la belleza de eso. –

+0

Las macros son un poco diferentes a Lisp ya que no se evalúan y un grupo de operadores especiales. No creo que pueda crear macros con Lisp (en el sentido de que no puede agregar macros a su lisp con solo un conjunto de funciones). –

+0

No puede agregar funciones (o variables, o operadores especiales, o ...) a su Lisp con un grupo de macros, tampoco. ¿Entonces las funciones también son un lenguaje por derecho propio? –

1

Lisp admite una forma de "metaprogramación", aunque no en el mismo sentido que la metaprogramación de plantillas C++. Además, su término "estático" podría significar cosas diferentes en este contexto, pero Lisp también admite el tipado estático, si eso es lo que quiere decir.

+0

Entiendo que la "metaprogramación estática" significa transformación de código en tiempo de compilación en lugar de comportamiento de interceptación/cambio dinámico en tiempo de ejecución (como con metaclases o EVAL, por ejemplo). En este sentido, las macros Lisp son un tipo de instalación de metaprogramación estática. OP, ¿es esto lo que quieres decir? –

+0

Hay un buen motivo por el que lisp se ha denominado el "lenguaje de programación programable".Permite/fomenta una forma mucho más general de "metaprogramación" que cosas como el enfoque de la plantilla de C++. – simon

+0

@Matias, sí, eso es lo que quiero decir. ¡Gracias! – jwfearn

12

Nemerle y Boo son mis favoritos personales para tales cosas. Nemerle tiene una sintaxis macro muy elegante, a pesar de su documentación deficiente. La documentación de Boo es excelente, pero sus macros son un poco menos elegantes. Sin embargo, ambos funcionan increíblemente bien.

Ambos se dirigen a .NET, por lo que pueden interoperar fácilmente con C# y otros lenguajes .NET, incluso con los binarios de Java, si usa IKVM.

Editar: Para aclarar, quiero decir macros en el sentido de Lisp de la palabra, no macros de preprocesador de C. Estos permiten la definición de nueva sintaxis y metaprogramación pesada en tiempo de compilación. Por ejemplo, Nemerle se envía con macros que validarán sus consultas SQL contra su servidor SQL en tiempo de compilación.

+0

Gracias por sus respuestas, ¿podría editar para agregar enlaces a Nemerle y Boo? – jwfearn

+1

El sitio para Nemerle es http://nemerle.org. Boo se encuentra en http://boo.codehaus.org/ – catbert

+0

Nemerle link: http://code.google.com/p/nemerle –

5

Recomiendo Haskell. Aquí hay un paper que describe sus capacidades de metaprogramación en tiempo de compilación.

7

El "D" programming language es similar a C++, pero tiene una compatibilidad de metaprogramación mucho mejor. He aquí un ejemplo de un trazador de rayos escrito utilizando solamente en tiempo de compilación metaprogramming:

Ctrace

Además, hay una rama gcc llamado "Concepto GCC" que apoya contructs metaprogramación que C++ no lo hace (al menos no todavía).

Concept GCC

+0

+1: D se ve muy bien –

2

'metaprogramming' es realmente un mal nombre para esta función específica, por lo menos cuando se está discutiendo más de un idioma, ya que esta función sólo es necesario para un pequeño sector de las lenguas que son:

  • estática
  • compilado a lenguaje de máquina
  • muy optimizado para un rendimiento en tiempo de compilación
  • exte nsible con tipos de datos definidos por el usuario (programación orientada a objetos en C++ 'caso s)
  • muy populares

llevar a cabo cualquiera de estos, y 'metaprogramming estática', simplemente no tiene sentido.por lo tanto, me sorprendería si algún lenguaje remotamente dominante tuviera algo así, como se entiende en C++.

por supuesto, los lenguajes dinámicos y varios lenguajes funcionales admiten conceptos totalmente diferentes que también se podrían llamar metaprogramación.

13

metaprogramming plantilla es esencialmente el abuso del mecanismo de plantilla. Lo que quiero decir es que obtienes básicamente lo que esperarías de una característica que era un efecto secundario no planeado --- es un desastre, y (aunque las herramientas están mejorando) un verdadero dolor en el culo porque el lenguaje no lo hace te apoyo para hacerlo (debo notar que mi experiencia con el estado del arte sobre esto está desactualizada, ya que esencialmente renuncié al enfoque. Sin embargo, no he oído hablar de grandes avances)

Jugar con esto en el '98 fue lo que me llevó a buscar mejores soluciones. Podría escribir sistemas útiles que dependieran de él, pero eran infernales. Alcanzarme finalmente me llevó a Common Lisp. Claro, el mecanismo de la plantilla está completo, pero también lo es intercal.

Common Lisp hace la metaprogramación `derecha '. Usted tiene todo el poder del idioma disponible mientras lo hace, sin sintaxis especial, y debido a que el lenguaje es muy dinámico, puede hacer más con él.

Hay otras opciones, por supuesto. Ningún otro lenguaje que he usado hace metaprogramación mejor que Lisp, y es por eso que lo uso para el código de investigación. Sin embargo, hay muchas razones por las que quizás quieras intentar algo más, pero todo será una solución de compromiso. Puede ver Haskell/ML/OCaml, etc. Muchos lenguajes funcionales tienen algo que se acerca al poder de las macros Lisp. Puede encontrar algunas cosas específicas de .NET, pero todas son bastante marginales (en términos de base de usuarios, etc.). Ninguno de los grandes jugadores en idiomas usados ​​industrialmente tiene algo como esto, realmente.

+0

Gracias por su respuesta! MP con plantillas C++ es definitivamente desordenado (esa es una motivación para mi pregunta). Cuando/si C++ 0x está disponible en los proveedores del compilador, debería estar un poco más limpio, ya que muchas de las características del nuevo lenguaje son específicamente compatibles con MP. – jwfearn

+0

Abusa o no abusa, pero de hecho no tienes otra opción para escribir código genérico en C++. –

24

Permítanme enumerar un algunos detalles importantes sobre cómo metaprogramming funciona en Lisp (o scheme o slate, o elegir su idioma favorito "dinámica"):

  • al hacer metaprogramming en lisp usted no tiene que ocuparse de dos idiomas. el código de meta nivel está escrito en el mismo idioma que el código de nivel de objeto que genera. la metaprogramación no está limitada a dos niveles, y también es más fácil para el cerebro.
  • en lisp tiene el compilador disponible en tiempo de ejecución. de hecho, la distinción tiempo de compilación/tiempo de ejecución se siente muy artificial allí y está muy sujeta a dónde coloque su punto de vista. En lisp con una simple llamada de función, puede compilar funciones a instrucciones de máquina que puede usar a partir de ese momento como objetos de primera clase; es decir, pueden ser funciones sin nombre que puede mantener en una variable local o una tabla hash global, etc.
  • macros en lisp son muy simples: un conjunto de funciones rellenas en una tabla hash y entregadas al compilador. para cada forma que el compilador está a punto de compilar, consulta esa tabla hash. si encuentra una función, la llama en tiempo de compilación con el formulario original y, en lugar de la forma original, compila el formulario que devuelve esta función. (modulo algunos detalles no importantes) por lo que lisp macros son básicamente complementos para el compilador.
  • escribiendo una función lisp en lisp que evalúa el código de lisp es de aproximadamente dos páginas de código (esto generalmente se llama eval). en tal función, tienes todo el poder para introducir las nuevas reglas que quieras en el nivel meta. (Lo que es correr rápido se va a tomar un poco de esfuerzo ... aunque casi lo mismo que bootstrapping un nuevo idioma ... :)

ejemplos al azar de lo se puede implementar como una biblioteca de usuarios usando metaprogramming Lisp (estos son ejemplos reales de las bibliotecas de Common Lisp):

  • extender el lenguaje con continuaciones delimitados (hu.dwim.delico)
  • implementar un JS-a-Lisp-RPC macro que pueda usar en jav ascript (que se genera a partir de lisp). se expande en una mezcla de código js/lisp que publica automáticamente (en la solicitud http) todas las variables locales referenciadas, las decodifica en el lado del servidor, ejecuta el cuerpo del código lisp en el servidor y devuelve el valor de retorno al javascript lado.
  • complemento de prólogo al igual que dar marcha atrás a la lengua que muy se integra perfectamente con el código Lisp "normal" (ver gritón)
  • un XML templating extension a Common Lisp (incluye un ejemplo de macros lector que son plugins para el analizador Lisp)
  • una tonelada de pequeña DSL, como loop o iterate para facilitar el bucle
+1

Gracias por una excelente respuesta. Según otra respuesta, he estado revisando Clojure (una variante de Lisp que se ejecuta en la JVM). Puede que le resulte interesante. Una sugerencia: agregar más enlaces (por ejemplo, pizarra, cl-delico, gritar, etc.) la búsqueda está bien, pero un enlace ahorra tiempo a los lectores. – jwfearn

+1

para mí Clojure no es interesante. es simplemente más accesible para el 80% de la gente y, por lo tanto, se está volviendo más popular ... el lenguaje de programación kernel, el proyecto FONC en VPRI.org es realmente interesante. –

5

Common Lisp apoya programas que escriben programas de varias maneras diferentes.

1) Los datos del programa y el programa "árbol de sintaxis abstracta" son uniformes (S-expresiones!)

2) defmacro

3) macros Reader.

4) MOP

De éstos, el verdadero alucinante es MOP. Lea "El Arte del Protocolo Metaobject". ¡Te cambiará las cosas, lo prometo!

+0

Gracias por su respuesta, ¡definitivamente revisaré MOP! Una sugerencia: para ahorrarle tiempo a los lectores, edite la respuesta para agregar enlaces o información de publicación para sus referencias. – jwfearn

+0

rocas MOP; Kizcales ahora se encuentra en Aspect Oriented Programming, que se puede ver como MOP para Java, C#, etc. –

2

La familia de idiomas ML se diseñó específicamente para este fin. Una de las historias de éxito más famosas de OCaml es la biblioteca FFTW para FFT de alto rendimiento que es un código C generado casi en su totalidad por un programa OCaml.

Cheers, Jon Harrop.

2

La mayoría de la gente trata de encontrar un lenguaje que tiene la "reflexión final" para la auto-inspección y algo así como " eval "para reificar nuevo código. Dichos lenguajes son difíciles de encontrar (LISP es un contraejemplo principal) y ciertamente no son comunes.

Pero otro enfoque es utilizar un conjunto de herramientas que pueden inspeccionar, generar y manipular el código del programa. Jackpot es una herramienta como enfocada en Java. http://jackpot.netbeans.org/

Nuestra DMS reingeniería de software Toolkit es tal herramienta, que funciona en C, C++, C#, Java, COBOL, PHP, Javascript , Ada, Verilog, VHDL y variedad de otros idiomas. (Utiliza interfaces de calidad de producción para que pueda leer todos estos idiomas). Mejor, puede hacerlo con múltiples idiomas en el mismo instante. Ver http://www.semdesigns.com/Products/DMS/DMSToolkit.html

DMS tiene éxito porque proporciona un método y un apoyo a la infraestructura regular para un acceso completo a la estructura del programa como AST, y en la mayoría de casos, los datos adicionales de tal análisis de tablas de símbolos, información de tipo, el control y el flujo de datos, todo lo necesario para hacer una manipulación sofisticada del programa.

3

Nim es un lenguaje de programación relativamente nuevo que tiene un amplio soporte para meta-programación estática y produce código compilado eficiente (como C++).

http://nim-lang.org/

Soporta tiempo de compilación transformaciones evaluación de la función, código de AST Lisp-como a través de macros, en tiempo de compilación reflexión, tipos genéricos que pueden ser parametrizada con valores arbitrarios, y reescritura término que se puede utilizar para crear Optimizaciones de mirilla de alto nivel con reconocimiento de tipo definidas por el usuario. Incluso es posible ejecutar programas externos durante el proceso de compilación que pueden influir en la generación del código. Como ejemplo, considere hablar con un servidor de base de datos que se ejecuta localmente para verificar que la definición de ORM en su código (suministrada a través de alguna DSL) coincida con el esquema de la base de datos.

Cuestiones relacionadas