stringtranslate.com

Metaprogramación

La metaprogramación es una técnica de programación informática en la que los programas informáticos tienen la capacidad de tratar a otros programas como si fueran sus datos . Esto significa que un programa puede diseñarse para leer, generar, analizar o transformar otros programas, e incluso modificarse a sí mismo, mientras se ejecuta. [1] [2] En algunos casos, esto permite a los programadores minimizar la cantidad de líneas de código para expresar una solución, lo que a su vez reduce el tiempo de desarrollo. [3] También permite a los programas una mayor flexibilidad para manejar de manera eficiente nuevas situaciones sin tener que volver a compilar.

La metaprogramación se puede utilizar para mover cálculos del tiempo de ejecución al tiempo de compilación , para generar código utilizando cálculos en tiempo de compilación y para permitir la automodificación del código . La capacidad de un lenguaje de programación de ser su propio metalenguaje permite la programación reflexiva , y se denomina reflexión . [4] La reflexión es una característica valiosa del lenguaje para facilitar la metaprogramación.

La metaprogramación fue popular en los años 1970 y 1980, cuando se usaban lenguajes de procesamiento de listas como Lisp . El hardware de la máquina Lisp ganó notoriedad en los años 1980 y permitió el desarrollo de aplicaciones que podían procesar código. A menudo se usaban para aplicaciones de inteligencia artificial .

Aproches

La metaprogramación permite a los desarrolladores escribir programas y desarrollar código que se enmarca en el paradigma de programación genérica . También es muy útil que el lenguaje de programación en sí sea un tipo de datos de primera clase (como en Lisp , Prolog , SNOBOL o Rebol ); esto se conoce como homoiconicidad . La programación genérica invoca una función de metaprogramación dentro de un lenguaje al permitir escribir código sin la preocupación de especificar tipos de datos, ya que se pueden proporcionar como parámetros cuando se utilizan.

La metaprogramación generalmente funciona de una de tres maneras. [5]

  1. El primer enfoque es exponer los componentes internos del sistema de ejecución (motor) al código de programación a través de interfaces de programación de aplicaciones (API) como la del emisor del lenguaje intermedio común (CIL) de .NET .
  2. El segundo enfoque es la ejecución dinámica de expresiones que contienen comandos de programación, a menudo compuestos de cadenas, pero también pueden ser de otros métodos que utilizan argumentos o contexto, como JavaScript . [6] Por lo tanto, "los programas pueden escribir programas". Aunque ambos enfoques se pueden utilizar en el mismo lenguaje, la mayoría de los lenguajes tienden a inclinarse hacia uno u otro.
  3. El tercer enfoque consiste en salirse completamente del lenguaje. Los sistemas de transformación de programas de propósito general, como los compiladores , que aceptan descripciones de lenguajes y realizan transformaciones arbitrarias en esos lenguajes, son implementaciones directas de metaprogramación general. Esto permite que la metaprogramación se aplique a prácticamente cualquier lenguaje de destino sin tener en cuenta si ese lenguaje de destino tiene alguna capacidad de metaprogramación propia. Se puede ver esto en funcionamiento con Scheme y cómo permite abordar algunos límites que se enfrentan en C mediante el uso de construcciones que son parte del lenguaje Scheme para extender C. [7]

Lisp es probablemente el lenguaje por excelencia con facilidades de metaprogramación, tanto por su precedencia histórica como por la simplicidad y potencia de su metaprogramación. En la metaprogramación de Lisp, el operador de comillas (normalmente una coma) introduce código que se evalúa en el momento de la definición del programa en lugar de en el momento de la ejecución. El lenguaje de metaprogramación es, por tanto, idéntico al lenguaje de programación anfitrión, y las rutinas Lisp existentes se pueden reutilizar directamente para la metaprogramación si se desea. Este enfoque se ha implementado en otros lenguajes incorporando un intérprete en el programa, que trabaja directamente con los datos del programa. Existen implementaciones de este tipo para algunos lenguajes de alto nivel comunes, como Pascal Script for Object Pascal de RemObjects .

Usos

Generación de código

Un ejemplo simple de un metaprograma es este script de Shell POSIX , que es un ejemplo de programación generativa :

#!/bin/sh # metaprograma echo '#!/bin/sh' > programa para i en $( seq 992 ) do echo "echo $i " >> programa hecho
chmod +x programa             

Este script (o programa) genera un nuevo programa de 993 líneas que imprime los números del 1 al 992. Esto es solo una ilustración de cómo usar código para escribir más código; no es la forma más eficiente de imprimir una lista de números. No obstante, un programador puede escribir y ejecutar este metaprograma en menos de un minuto, y habrá generado más de 1000 líneas de código en ese lapso de tiempo.

Un quine es un tipo especial de metaprograma que produce su propio código fuente como salida. Los quines suelen tener un interés lúdico o teórico únicamente.

No toda la metaprogramación implica programación generativa. Si los programas se pueden modificar en tiempo de ejecución o si está disponible la compilación incremental (como en C# , Forth , Frink , Groovy , JavaScript , Lisp , Elixir , Lua , Nim , Perl , PHP , Python , Rebol , Ruby , Rust , R , SAS , Smalltalk y Tcl ), se pueden utilizar técnicas para realizar metaprogramación sin generar código fuente.

Un estilo de enfoque generativo es el empleo de lenguajes específicos de dominio (DSL). Un ejemplo bastante común de uso de DSL implica la metaprogramación generativa: lex y yacc , dos herramientas utilizadas para generar analizadores y analizadores léxicos , que permiten al usuario describir el lenguaje mediante expresiones regulares y gramáticas independientes del contexto , e incorporar los algoritmos complejos necesarios para analizar el lenguaje de manera eficiente.

Instrumentación de código

Uno de los usos de la metaprogramación es instrumentar programas para realizar análisis dinámicos de programas .

Desafíos

Algunos argumentan que existe una curva de aprendizaje pronunciada para hacer un uso completo de las características de la metaprogramación. [8] Dado que la metaprogramación brinda más flexibilidad y capacidad de configuración en tiempo de ejecución, el uso incorrecto o incorrecto de la metaprogramación puede resultar en errores injustificados e inesperados que pueden ser extremadamente difíciles de depurar para un desarrollador promedio. Puede introducir riesgos en el sistema y hacerlo más vulnerable si no se usa con cuidado. Algunos de los problemas comunes que pueden ocurrir debido al uso incorrecto de la metaprogramación son la incapacidad del compilador para identificar los parámetros de configuración faltantes, los datos inválidos o incorrectos pueden resultar en una excepción desconocida o resultados diferentes. [9] Debido a esto, algunos creen [8] que solo los desarrolladores altamente capacitados deberían trabajar en el desarrollo de características que ejerciten la metaprogramación en un lenguaje o plataforma y los desarrolladores promedio deben aprender a usar estas características como parte de la convención.

Usos en lenguajes de programación

Sistemas macro

Ensambladores de macros

El IBM/360 y sus derivados tenían potentes funciones de ensamblador de macros que se utilizaban a menudo para generar programas completos en lenguaje ensamblador [ cita requerida ] o secciones de programas (para diferentes sistemas operativos, por ejemplo). Las macros proporcionadas con el sistema de procesamiento de transacciones CICS tenían macros de ensamblador que generaban instrucciones COBOL como paso de preprocesamiento.

Otros ensambladores, como MASM , también admiten macros.

Metaclases

Las metaclases son proporcionadas por los siguientes lenguajes de programación:

Metaprogramación de plantillas

Metaprogramación por etapas

Tipos dependientes

El uso de tipos dependientes permite demostrar que el código generado nunca es inválido. [15] Sin embargo, este enfoque es de vanguardia y rara vez se encuentra fuera de los lenguajes de programación de investigación.

Implementaciones

La lista de sistemas de metaprogramación notables se mantiene en Lista de sistemas de transformación de programas .

Véase también

Referencias

  1. ^ Sondergaard, Harald (2013). «Curso de análisis y transformación de programas» . Consultado el 18 de septiembre de 2014 .
  2. ^ Czarnecki, Krzysztof ; Eisenecker, Ulrich W. (2000). Programación Generativa . ISBN 0-201-30977-7.
  3. ^ Walker, Max. "El arte de la metaprogramación en Java". New Circle . Consultado el 28 de enero de 2014 .
  4. ^ Krauss, Aaron. "Conceptos de programación: introspección y reflexión de tipos". The Societa . Consultado el 14 de septiembre de 2014 .
  5. ^ Joshi, Prateek (5 de abril de 2014). «¿Qué es la metaprogramación? – Parte 2/2». Perpetual Enigma . Consultado el 14 de agosto de 2014 .
  6. ^ Por ejemplo, instance_eval en Ruby toma una cadena o una función anónima. "Rdoc para la clase: BasicObject (Ruby 1.9.3) - instance_eval" . Consultado el 30 de diciembre de 2011 .
  7. ^ "El arte de la metaprogramación". IBM .
  8. ^ ab Bicking, Ian. "El desafío de la metaprogramación". IanBicking.org . Consultado el 21 de septiembre de 2016 .
  9. ^ Terry, Matt (21 de agosto de 2013). "Cuidado con la metaprogramación". Medium.com . Medium Corporation . Consultado el 21 de agosto de 2014 .
  10. ^ A través del "Protocolo de Metaobjetos" del Sistema de Objetos Common Lisp
  11. ^ "Metaprogramación de plantillas de C++". aszt.inf.elte.hu . Consultado el 23 de julio de 2022 .
  12. ^ Lisp (lenguaje de programación) "Formas de autoevaluación y comillas", operador de cuasi-comillas.
  13. ^ "LMS: Generación de programas y compiladores integrados en Scala". scala-lms.github.io . Consultado el 6 de diciembre de 2017 .
  14. ^ Rompf, Tiark; Odersky, Martin (junio de 2012). "Preparación modular ligera: un enfoque pragmático para la generación de código en tiempo de ejecución y DSL compilados". Comunicaciones de la ACM . 55 (6): 121–130. doi :10.1145/2184319.2184345. ISSN  0001-0782. S2CID  52898203.
  15. ^ Chlipala, Adam (junio de 2010). "Ur: metaprogramación estáticamente tipada con cálculo de registros a nivel de tipo" (PDF) . ACM SIGPLAN Notices . PLDI '10. 45 (6): 122–133. doi :10.1145/1809028.1806612 . Consultado el 29 de agosto de 2012 .

Enlaces externos