sirve que para link etiquetas etiqueta ejemplos definicion body atributos metaprogramming d d2

metaprogramming - que - title html ejemplos



Ejemplos de para qué se pueden usar las plantillas de D (4)

He oído que el lenguaje D tiene potentes funciones de metaprogramación para ejecutar funciones en tiempo de compilación. Eso suena muy emocionante, pero me resulta difícil pensar en ejemplos prácticos de cosas que son difíciles de lograr sin ellos.

¿Alguien puede dar algunos ejemplos de situaciones en las que las funciones de metaprogramación de D sean muy útiles?


El uso más interesante en la práctica que conozco es una biblioteca que escribí * para usar el comprobador de tipos para reforzar la seguridad de la unidad (es decir, está prohibido agregar distancias a los tiempos y proporcionar la conversión correcta al agregar metros a pies). Lo mismo se puede y se ha hecho en C ++, pero hacerlo en D en tiempo de compilación es un poco más difícil de lo que sería hacerlo en tiempo de ejecución.

* Perdón por el descarado enchufe.


No estoy bien versado en los propósitos de la meta-programación. Aquí está mi opinión sobre las tres construcciones principales encontradas en D.

  • La evaluación de la función de tiempo de compilación se trata del rendimiento. Hacer que el compilador haga el mayor trabajo posible para que se haga menos una vez que el programa se ejecute.
    • Como construir un caché de números primos, si el programa los utiliza a menudo.
  • Las plantillas tratan de eliminar la duplicación de algoritmos. No es solo la programación genérica, pero como D tiene CTFE, no es necesaria en los mismos casos que C ++.
  • Los mixins se tratan de poder generar código en tiempo de compilación que se agrega al programa. Se basa en cosas como plantillas y CTFE, pero sigue siendo una pieza importante que no proporcionan los demás.

Si desea ejemplos prácticos de cómo usar las facilidades de metaprogramación de D (CTFE, o la evaluación de la función de compilación de tiempo, es solo uno de estos, y ni siquiera el más importante) no busque más, Phobos, la biblioteca estándar de D2. Gran parte de este código está escrito por Andrei Alexandrescu, quien inventó muchas de las técnicas de metaprogramación de plantillas en C ++, y ahora está trabajando con Walter Bright en el diseño e implementación de D.

Los mejores módulos para mirar son std.range y std.algorithm . Estos están casi completamente compuestos de plantillas, fueron diseñados por Andrei y son sorprendentemente legibles dada la cantidad de metaprogramación que utilizan. He contribuido significativamente a estos dos módulos y leer el código que estaba allí cuando comencé fue básicamente cómo aprendí.

Todo el código está licenciado bajo la licencia Boost (extremadamente permisiva) y puede verse directamente desde su navegador en el sitio de Phobos Trac en dsource.org.

Para brindarle una hoja de ruta de lo que está viendo, las instalaciones de metaprogramación de D básicamente se dividen en 4 categorías:

  1. Plantillas , que son básicamente como las plantillas de C ++, pero con algunas características agregadas como static if , static assert stert, variadic templates y restricciones, que son básicamente conceptos similares pero más simples.

  2. Compilación tiempo reflexión / introspección . Esto incluye las expresiones incorporadas is() y __traits , así como el módulo de biblioteca estándar std.traits.

  3. Mixins . Estos le permiten tomar una plantilla (mixins de plantilla) o una cadena de tiempo de compilación (mixins de cadena) y evaluarla como código en el ámbito actual. Las combinaciones de cadenas se pueden considerar como una especie de sentencia eval, excepto que la cadena se evalúa como código en tiempo de compilación en lugar de en tiempo de ejecución.

  4. Evaluación de la función de tiempo de compilación, o CTFE , que permite evaluar las funciones que cumplen ciertos criterios en el momento de la compilación. Un uso importante de CTFE es que, combinado con las combinaciones de cadenas, puede generar código como una cadena en el momento de la compilación y luego evaluarla como código en el ámbito donde se produce la declaración de la mixin . Para ver ejemplos de esto, vea std.range.Lockstep y std.range.OutputRangeObject, que recientemente ingresé en las versiones SVN de Phobos.


Un uso realmente interesante y práctico de la ejecución de la función de tiempo de compilación es para generar código en tiempo de compilación, posiblemente desde archivos de configuración, o tal vez scripts.

Aquí hay un ejemplo simple de procesar un archivo en tiempo de compilación.

main.d

string make_ints(string s) { string ret = ""; foreach (varname; split(s)) ret ~= "int " ~ varname ~ "; "; return ret; } void main() { mixin(make_ints(import("script"))); foo = 1; bar = 2; xyz = 3; }

guión

foo bar xyz

En el momento de la compilación, el archivo "script" se leerá, se dividirá en espacios y luego make_ints devuelve int foo; int bar; int xyz; int foo; int bar; int xyz; directamente en el código D, listo para usar esas variables.

Si bien este es un ejemplo inútil, puede ver fácilmente cómo se puede usar para leer valores de un archivo de configuración (tal vez valores para el tamaño de un caché, o algo así). Los juegos podrían hacer uso de esto para generar código D en bruto a partir de scripts, lo que será excelente para el rendimiento (normalmente los juegos recurren al uso de código interpretado para scripts y sufren rendimiento).

También puede usar esto para la optimización automática del rendimiento. Digamos que tienes algunas X constantes, que se pueden modificar para afectar el rendimiento de varias maneras, pero no sabes qué valor de X te dará el mejor rendimiento. Podría poner X en un archivo, leerlo en tiempo de compilación para su uso, probar otros valores en tiempo de ejecución y volver a colocar el mejor en el archivo. De esa manera, obtendrá un rendimiento mejorado gradualmente sin tener que hacer nada manualmente.