metaprogramming - tag - metaprogramacion ruby
¿Qué es exactamente la metaprogramación? (7)
La metaprogramación es la escritura de programas informáticos que escriben o manipulan otros programas (o ellos mismos) como sus datos, o que hacen parte del trabajo en tiempo de ejecución que de otro modo se realizaría en tiempo de compilación. En muchos casos, esto permite a los programadores realizar más tareas en la misma cantidad de tiempo que tardarían en escribir todo el código de forma manual, o les da a los programas una mayor flexibilidad para manejar nuevas situaciones de manera eficiente sin necesidad de volver a compilarlas. ( Source )
Básicamente, es el código de escritura que genera más código, que se ejecuta para lograr algún objetivo. Esto generalmente se hace en el mismo idioma (usando javascript para crear una cadena de javascript, luego eval
) o para emitir otro idioma (usando .NET para crear un archivo de lote de Windows).
Estaba leyendo un artículo sobre TheServerSide en la programación de ployglot en la plataforma Java . Algunos comentarios en el artículo se refieren a la metaprogramación como la capacidad de generar código (tal vez sobre la marcha).
La metaprogramación es la capacidad de generar código sobre la marcha o la capacidad de inyectar métodos y atributos en objetos existentes en el tiempo de ejecución (como lo permiten algunos lenguajes dinámicos como Python, Ruby y Groovy).
Bueno, la metaprogramación es solo programación, pero básicamente es "escribir código que escribe código" .
La capacidad que mencionas cuando un programa puede observar y modificar su propia estructura y comportamiento se llama reflexión y es un tipo de metaprogramación.
Los lenguajes de tipado dinámico tienen potentes funciones de reflexión en tiempo de ejecución, que son posibles gracias a la naturaleza interpretada de estos lenguajes ...
Los lenguajes de tipo estático también tienen potentes técnicas de metaprogramación, por ejemplo, la metaprogramación de plantillas de C ++ ...
Esta es solo mi opinión personal, que es probablemente la definición más liberal de metaprogramación.
Creo que incluye:
- Generación de código de compilación o generación de código de tiempo de ejecución (o ambos)
- Pensamiento orientado a aspectos o programación orientada a aspectos
- Pensamiento DRY
Creo que puedes llegar usando cualquiera de estos y en combinación:
- Reflexión
- DSL (idiomas específicos del dominio)
- Atributos (.NET) o Anotaciones (Java)
- Genéricos (.NET / Java)
- Plantillas (C ++)
- method_missing (Ruby)
- cierres / funciones de primera clase / delegados
- AOP - Programación Orientada a Aspectos
Gran pregunta Lamento mucho que ninguna de las respuestas realmente responda tu pregunta correctamente. Tal vez puedo ayudar ...
La definición de metaprogramación es bastante simple: significa programas que manipulan programas.
Su respuesta aceptada dice programas que se manipulan a sí mismos. Esos son de hecho metaprogramas, pero son un subconjunto de todos los metaprogramas.
Todas:
- Parsers
- Lenguajes específicos del dominio (DSL)
- Lenguajes específicos de dominio incrustados (EDSL)
- Compiladores
- Intérpretes
- Reescritura de términos
- Demostradores de teoremas
son metaprogramas. Entonces, el compilador de GCC es un metaprograma, el intérprete de CPython es un metaprograma, el sistema de álgebra computacional de Mathematica es un metaprograma, el probador de teoremas de Coq es un metaprograma y así sucesivamente.
Otras respuestas han afirmado que los metaprogramas son programas que generan otros programas. Esos son, de hecho, metaprogramas, pero, de nuevo, son un subconjunto de todos los metaprogramas. La biblioteca Fastest Fourier Transform in the West (FFTW) es un ejemplo de dicho metaprograma. El código fuente está escrito principalmente en OCaml y genera bits de código C (denominados codelets) que se combinan para crear rutinas de transformada rápida de Fourier de alto rendimiento optimizadas para máquinas específicas. Esa biblioteca en realidad se usa para proporcionar las rutinas de FFT en Matlab. La gente ha estado escribiendo programas para generar métodos numéricos durante décadas, desde los primeros días de FORTRAN .
El primer lenguaje de programación que integró el soporte para la metaprogramación fue el lenguaje LISt Processor (LISP) a fines de la década de 1950. LISP 1.5 incluía una serie de características que facilitaban la metaprogramación. En primer lugar, el tipo de datos básicos de LISP son listas anidadas, es decir, árboles como (a (bc) d)
, lo que significa que cualquier código LISP puede expresarse de forma nativa como una estructura de datos. Esto se conoce como homoiconicidad. En segundo lugar, el código LISP se puede convertir fácilmente en datos usando QUOTE. Por ejemplo (+ 1 2 3)
agrega 1 + 2 + 3 y (QUOTE (+ 1 2 3))
crea una expresión que agrega 1 + 2 + 3 cuando se evalúa. En tercer lugar, LISP proporcionó un evaluador meta-circular que le permite usar el intérprete o compilador de host para evaluar el código LISP en tiempo de ejecución, incluido el código LISP generado en tiempo de ejecución. Los descendientes de LISP incluyen Scheme y Clojure . En todos estos lenguajes, la metaprogramación se ve más comúnmente en forma de programas que se modifican a sí mismos, generalmente usando macros.
En la década de 1970, Robin Milner desarrolló un MetaLanguage (ML) que se convirtió en la familia ML de lenguajes de programación que incluye Standard ML y OCaml y que influyó fuertemente en Haskell y F# . Estos idiomas facilitan la expresión de otros idiomas. En estos lenguajes, los metaprogramas se ven más comúnmente en forma de lexers, analizadores sintácticos, intérpretes y compiladores.
En 1994, Erwin Unruh descubrió que el sistema de plantillas de C ++ estaba completo y podría usarse para ejecutar programas arbitrarios en tiempo de compilación . La metaprogramación de plantillas de C ++ trajo metaprogramación a las masas no lavadas que (ab) la usaron para muchas cosas diferentes, incluida la generación de métodos numéricos en la biblioteca Blitz ++ .
La metaprogramación está escribiendo un programa que genera otro programa. Esto es algo en lo que los lenguajes como Lisp son realmente buenos. Es mucho más fácil hacerlo en un lenguaje que admite macros reales (no macros C ++, sino más bien los que pueden manipular el código que producen) como Ruby, Lisp, Scheme, etc. que en un lenguaje como Java.
Una implementación es crear un "lenguaje específico de dominio" que sea una forma de mejorar un lenguaje de programación para realizar una tarea específica. Puede ser increíblemente poderoso si se hace correctamente. Ruby on Rails es un buen ejemplo de este tipo de programación.
Si está interesado en explorar este método, consulte la Estructura e Interpretación de Programas de Computadora, que es uno de los libros seminales que cubren el tema.
La metaprogramación se refiere a una variedad de formas en que un programa tiene conocimiento de sí mismo o puede manipularse a sí mismo.
En lenguajes como C #, la reflexión es una forma de metaprogramación, ya que el programa puede examinar información sobre sí mismo. Por ejemplo, devolver una lista de todas las propiedades de un objeto.
En lenguajes como ActionScript, puede evaluar funciones en tiempo de ejecución para crear nuevos programas como eval ("x" + i) .DoSomething () afectaría a un objeto llamado x1 cuando i es 1 y x2 cuando i es 2.
Finalmente, otra forma común de metaprogramación es cuando el programa puede cambiar a sí mismo en formas no triviales. LISP es bien conocido por esto y es algo que Paul Graham defendió hace aproximadamente una década. Tendré que buscar algunos de sus ensayos específicos. Pero la idea es que el programa cambie otra parte del programa en función de su estado. Esto permite un nivel de flexibilidad para tomar decisiones en tiempo de ejecución que es muy difícil en la mayoría de los lenguajes populares en la actualidad.
También vale la pena señalar que en los buenos tiempos de la programación en ensamble directo, los programas que se alteraban en el tiempo de ejecución eran necesarios y muy comunes.
Del ensayo de Paul Graham "What Made Lisp Different" :
Muchos idiomas tienen algo llamado macro. Pero las macros de Lisp son únicas. Y créanlo o no, lo que hacen está relacionado con los paréntesis. Los diseñadores de Lisp no pusieron todos esos paréntesis en el idioma para ser diferentes. Para el programador Blub, el código Lisp se ve raro. Pero esos paréntesis están ahí por una razón. Son la evidencia externa de una diferencia fundamental entre Lisp y otros lenguajes.
El código Lisp está hecho de objetos de datos Lisp. Y no en el sentido trivial de que los archivos fuente contienen caracteres, y las cadenas son uno de los tipos de datos admitidos por el lenguaje. El código Lisp, después de ser leído por el analizador, está hecho de estructuras de datos que puede recorrer.
Si usted entiende cómo funcionan los compiladores, lo que realmente está sucediendo no es tanto que Lisp tenga una sintaxis extraña ya que Lisp no tiene sintaxis. Se escriben programas en los árboles de análisis que se generan dentro del compilador cuando se analizan otros idiomas. Pero estos árboles de análisis son completamente accesibles para sus programas. Puedes escribir programas que los manipulen. En Lisp, estos programas se llaman macros. Son programas que escriben programas.
Programas que escriben programas? ¿Cuándo querrías hacer eso alguna vez? No muy a menudo, si piensas en Cobol. Todo el tiempo, si piensas en Lisp. Sería conveniente aquí si pudiera dar un ejemplo de una poderosa macro, ¡y decir allí! ¿Qué hay sobre eso? Pero si lo hiciera, parecería un galimatías para alguien que no conocía a Lisp; no hay espacio aquí para explicar todo lo que necesita saber para entender lo que significa. En Ansi Common Lisp intenté mover las cosas lo más rápido que pude, y aun así no llegué a las macros hasta la página 160.
Pero creo que puedo dar una clase de argumento que podría ser convincente. El código fuente del editor de Viaweb fue probablemente alrededor de 20-25% macros. Las macros son más difíciles de escribir que las funciones normales de Lisp, y se considera que es malo usarlas cuando no son necesarias. Entonces, cada macro en ese código está ahí porque tiene que ser así. Lo que eso significa es que al menos el 20-25% del código de este programa está haciendo cosas que no puedes hacer fácilmente en cualquier otro idioma. Por muy escéptico que el programador Blub se refiera a mis afirmaciones sobre los misteriosos poderes de Lisp, esto debería despertar su curiosidad. No estábamos escribiendo este código para nuestra propia diversión. Fuimos una pequeña startup, programamos lo más que pudimos para poner barreras técnicas entre nosotros y nuestros competidores.
Una persona sospechosa podría comenzar a preguntarse si hubo alguna correlación aquí. Una gran parte de nuestro código estaba haciendo cosas que son muy difíciles de hacer en otros idiomas. El software resultante hizo cosas que el software de nuestros competidores no pudo hacer. Tal vez hubo algún tipo de conexión. Te animo a que sigas ese hilo. Puede haber más en ese anciano cojeando en sus muletas de lo que parece.
Source tiene un buen artículo sobre el tema. Uno no tiene que hacer modificaciones de tiempo de ejecución para algo que califique como metaprogramación. Por ejemplo, muchas personas usan plantillas C ++ para hacer metaprogramación en tiempo de compilación.