haskell - Idiomas no C++ para programación generativa?
lisp clojure (14)
C ++ es probablemente el lenguaje más popular para metaprogramación estática y Java no lo admite .
¿Hay otros lenguajes además de C ++ que respalden la programación generativa (programas que crean programas)?
El lenguaje de programación "D" es similar a C ++, pero tiene un soporte de metaprogramación mucho mejor. Aquí hay un ejemplo de un ray-tracer escrito utilizando solo metaprogramación en tiempo de compilación:
Además, hay una rama de gcc llamada "Concept GCC" que admite metaprogramaciones que C ++ no hace (al menos no todavía).
El metalenguaje (ML), por supuesto: http://cs.anu.edu.au/student/comp8033/ml.html
La alternativa a la metaprogramación de estilo de plantilla es Macro-style que se ve en varias implementaciones de Lisp. Sugeriría descargar On Lisp de Paul Graham y también echar un vistazo a Clojure si está interesado en un Lisp con macros que se ejecuta 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.
La metaprogramación de la plantilla es esencialmente un abuso del mecanismo de la 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 señalar que mi experiencia con el estado del arte sobre esto está desactualizada, ya que esencialmente renuncié al enfoque. No he oído hablar de grandes avances, sin embargo)
Perseguirse 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 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.
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.
Recomiendo a Haskell . Aquí hay un documento que describe sus capacidades de metaprogramación en tiempo de compilación.
Common Lisp admite programas que escriben programas de diferentes maneras.
1) Los datos del programa y el programa "árbol sintáctico abstracto" son uniformes (¡expresiones S!)
2) defmacro
3) macros de lector.
4) MOP
De estos, el verdadero soplador de mente es MOP. Lea "El Arte del Protocolo Metaobject". ¡Te cambiará las cosas, lo prometo!
Mucho trabajo en Haskell: idiomas específicos de dominio (DSL), especificaciones ejecutables, transformación de programa, aplicación parcial, cálculo por etapas. Pocos enlaces para comenzar:
La familia de idiomas ML se diseñó específicamente para este propósito. 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.
Saludos, Jon Harrop.
La mayoría de las personas trata de encontrar un lenguaje que tenga "reflejo final" para la autoinspección y algo así como "eval" para reificar el nuevo código. Tales idiomas son difíciles de encontrar (LISP es un contraejemplo primordial) y ciertamente no son convencionales.
Pero otro enfoque es utilizar un conjunto de herramientas que puedan inspeccionar, generar y manipular el código del programa. Jackpot es una herramienta enfocada en Java. http://jackpot.netbeans.org/
Nuestro kit de herramientas de reingeniería de software DMS es una herramienta que funciona en C, C ++, C #, Java, COBOL, PHP, Javascript, Ada, Verilog, VHDL y una variedad de otros lenguajes. (Utiliza interfaces de calidad de producción para que pueda leer todos estos idiomas). Mejor, puede hacer esto 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 regular e infraestructura de soporte para acceso completo a la estructura del programa como AST y, en la mayoría de los casos, datos adicionales como tablas de símbolos, información de tipo, control y análisis de flujo de datos, todo lo necesario para manipular sofisticadamente el programa.
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 interactuar fácilmente con C # y otros lenguajes .NET, incluso 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.
''metaprogramación'' es realmente un mal nombre para esta característica específica, al menos cuando se habla de más de un idioma, ya que esta función solo es necesaria para un segmento reducido de idiomas que son:
- estático
- compilado a lenguaje de máquina
- muy optimizado para el rendimiento en tiempo de compilación
- extensible con tipos de datos definidos por el usuario (OOP en el caso de C ++)
- muy popular
sacar uno de estos, y ''metaprogramación 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.
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 ++).
Admite la evaluación de funciones en tiempo de compilación, transformaciones de código AST similares a lisp a través de macros, reflexión en tiempo de compilación, tipos genéricos que se pueden parametrizar con valores arbitrarios y reescritura de términos que se pueden usar para crear tipos de alto nivel definidos por el usuario optimizaciones de mirilla. 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.
Permítanme enumerar algunos detalles importantes sobre cómo funciona la metaprogramación en lisp (o esquema , o pizarra , o elige su idioma "dinámico" favorito):
- Cuando haces metaprogramación en lisp , no tienes que lidiar con 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 tienes 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, una tabla hash global, etc.
- Las 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 .
- escribir una función de 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. (Hacerlo correr rápido va a tomar un poco de esfuerzo ... casi lo mismo que poner en marcha un nuevo idioma ... :)
ejemplos al azar de lo que puede implementar como una biblioteca de usuario utilizando la metaprogramación lisp (estos son ejemplos reales de bibliotecas de lisp comunes):
- extender el idioma con continuaciones delimitadas (hu.dwim.delico)
- implemente una macro js-to-lisp-rpc que puede usar en javascript (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.
- agrega prolog como retroceder al idioma que se integra perfectamente con el código de lisp "normal" (ver chámer)
- una extensión de plantillas XML para lisp común (incluye un ejemplo de macros de lector que son complementos para el analizador de lisp)
- una tonelada de pequeñas DSL, como bucle o iterar para bucle fácil