Qu'est-ce que la métaprogrammation exactement?


128

Je lisais un article sur TheServerSide sur la programmation ployglot sur la plateforme Java . Certains commentaires dans l'article font référence à la métaprogrammation comme étant la capacité de générer du code (peut-être à la volée).

La métaprogrammation a-t-elle la capacité de générer du code à la volée ou est-ce la capacité d'injecter des méthodes et des attributs dans des objets existants au moment de l'exécution (comme ce que permettent certains langages dynamiques comme Python, Ruby et Groovy).


7
Vous pourriez être intéressé par cette réponse stackoverflow.com/questions/2565572/…
ewernli

@ewernli: Cette réponse est en fait meilleure que n'importe laquelle des réponses ici!
JD

Réponses:


100

La métaprogrammation fait référence à une variété de façons dont un programme se connaît ou peut se manipuler.

Dans des langages comme C #, la réflexion est une forme de métaprogrammation puisque le programme peut examiner des informations sur lui-même. Par exemple, renvoyer une liste de toutes les propriétés d'un objet.

Dans des langages comme ActionScript, vous pouvez évaluer les fonctions au moment de l'exécution pour créer de nouveaux programmes tels que eval ("x" + i). DoSomething () affecterait un objet appelé x1 lorsque i est 1 et x2 lorsque i est 2.

Enfin, une autre forme courante de métaprogrammation est lorsque le programme peut se changer de manière non triviale. LISP est bien connu pour cela et c'est quelque chose que Paul Graham a défendu il y a une dizaine d'années. Je vais devoir consulter certains de ses essais spécifiques. Mais l'idée est que le programme changerait une autre partie du programme en fonction de son état. Cela permet un niveau de flexibilité pour prendre des décisions au moment de l'exécution qui est très difficile dans la plupart des langues courantes aujourd'hui.

Il est également intéressant de noter qu'au bon vieux temps de la programmation en assemblage direct, les programmes qui se modifiaient au moment de l'exécution étaient nécessaires et très courants.

Extrait de l'essai de Paul Graham "What Made Lisp Different" :

De nombreuses langues ont quelque chose appelé une macro. Mais les macros Lisp sont uniques. Et croyez-le ou non, ce qu'ils font est lié aux parenthèses. Les concepteurs de Lisp n'ont pas mis toutes ces parenthèses dans le langage juste pour être différent. Pour le programmeur Blub, le code Lisp semble bizarre. Mais ces parenthèses sont là pour une raison. Ils sont la preuve extérieure d'une différence fondamentale entre Lisp et d'autres langages.

Le code Lisp est constitué d'objets de données Lisp. Et pas dans le sens trivial du fait que les fichiers source contiennent des caractères et que les chaînes sont l'un des types de données pris en charge par le langage. Le code Lisp, après avoir été lu par l'analyseur, est constitué de structures de données que vous pouvez parcourir.

Si vous comprenez comment les compilateurs fonctionnent, ce qui se passe réellement n'est pas tant que Lisp a une syntaxe étrange que Lisp n'a pas de syntaxe. Vous écrivez des programmes dans les arborescences d'analyse qui sont générés dans le compilateur lorsque d'autres langages sont analysés. Mais ces arbres d'analyse sont entièrement accessibles à vos programmes. Vous pouvez écrire des programmes qui les manipulent. En Lisp, ces programmes sont appelés macros. Ce sont des programmes qui écrivent des programmes.

Des programmes qui écrivent des programmes? Quand voudriez-vous faire ça? Pas très souvent, si vous pensez en Cobol. Tout le temps, si vous pensez en Lisp. Ce serait pratique ici si je pouvais donner un exemple de macro puissante, et dire là! et ça? Mais si je le faisais, cela ressemblerait à du charabia pour quelqu'un qui ne connaissait pas Lisp; il n'y a pas de place ici pour expliquer tout ce que vous devez savoir pour comprendre ce que cela signifie. Dans Ansi Common Lisp, j'ai essayé de faire avancer les choses aussi vite que possible, et même ainsi je ne suis pas arrivé aux macros avant la page 160.

Mais je pense que je peux donner une sorte d'argument qui pourrait être convaincant. Le code source de l'éditeur Viaweb était probablement composé d'environ 20 à 25% de macros. Les macros sont plus difficiles à écrire que les fonctions Lisp ordinaires, et il est considéré comme un mauvais style de les utiliser lorsqu'elles ne sont pas nécessaires. Donc, chaque macro de ce code est là parce qu'elle doit l'être. Cela signifie qu'au moins 20 à 25% du code de ce programme fait des choses que vous ne pouvez pas faire facilement dans une autre langue. Aussi sceptique que puisse être le programmeur de Blub à propos de mes prétentions sur les pouvoirs mystérieux de Lisp, cela devrait le rendre curieux. Nous n'écrivions pas ce code pour notre propre amusement. Nous étions une toute petite startup, programmant aussi dur que possible afin de mettre des barrières techniques entre nous et nos concurrents.

Une personne suspecte pourrait commencer à se demander s'il y avait une corrélation ici. Une grande partie de notre code faisait des choses qui sont très difficiles à faire dans d'autres langues. Le logiciel résultant a fait des choses que les logiciels de nos concurrents ne pouvaient pas faire. Peut-être qu'il y avait une sorte de connexion. Je vous encourage à suivre ce fil. Il y a peut-être plus à ce vieil homme qui boitille sur ses béquilles qu'il n'y paraît.


6
N'oubliez pas la métaprogrammation des modèles en C ++. La capacité d'exécuter des expressions et de prendre des décisions au moment de la compilation, et de faire compiler les résultats de manière statique dans l'exécutable final.
Remy Lebeau

1
J'ai été choqué in order to put technical barriers between us and our competitorset c'est tamade correct.
Evan Hu

4
Les programmes qui se manipulent sont un sous-ensemble de tous les métaprogrammes. La métaprogrammation en général signifie simplement des programmes qui manipulent des programmes.
JD

55

Excellente question. Je suis vraiment désolé de voir qu'aucune des réponses actuellement ne répond correctement à votre question. Peut-être que je peux aider ...

La définition de la métaprogrammation est vraiment assez simple: cela signifie des programmes qui manipulent des programmes.

Votre réponse acceptée dit des programmes qui se manipulent. Ce sont en effet des métaprogrammes mais ils sont un sous-ensemble de tous les métaprogrammes.

Tout:

  • Analyseurs
  • Langages spécifiques au domaine (DSL)
  • Langages spécifiques à un domaine intégré (EDSL)
  • Compilateurs
  • Interprètes
  • Réécrivains de termes
  • Prouveurs de théorème

sont des métaprogrammes. Donc le compilateur GCC est un métaprogramme, l' interpréteur CPython est un métaprogramme, le système d'algèbre informatique Mathematica est un métaprogramme, le prouveur du théorème Coq est un métaprogramme et ainsi de suite.

D'autres réponses ont affirmé que les métaprogrammes sont des programmes qui génèrent d'autres programmes. Ce sont en effet des métaprogrammes mais, encore une fois, ils sont un sous-ensemble de tous les métaprogrammes. La bibliothèque FFTW (Fastest Fourier Transform in the West ) est un exemple d'un tel métaprogramme. Le code source est écrit principalement en OCaml et génère des bits de code C (appelés codelets) qui sont combinés pour créer des routines de transformation rapide de Fourier hautes performances optimisées pour des machines spécifiques. Cette bibliothèque est en fait utilisée pour fournir les routines FFT dans Matlab. Les gens ont écrit des programmes pour générer des méthodes numériques pendant des décennies, depuis les débuts de FORTRAN .

Le premier langage de programmation intégrant la prise en charge de la métaprogrammation était le langage LISt Processor (LISP) à la fin des années 1950. LISP 1.5 comprenait un certain nombre de fonctionnalités qui facilitaient la métaprogrammation. Premièrement, le type de données principal de LISP est constitué de listes imbriquées, c'est-à-dire d'arbres comme (a (b c) d), ce qui signifie que tout code LISP peut être exprimé nativement sous forme de structure de données. Ceci est connu sous le nom d'homoiconicité. Deuxièmement, le code LISP peut être facilement converti en données à l'aide de QUOTE. Par exemple, (+ 1 2 3)ajoute 1 + 2 + 3 et (QUOTE (+ 1 2 3))crée une expression qui ajoute 1 + 2 + 3 lorsqu'elle est évaluée. Troisièmement, LISP a fourni un évaluateur méta-circulaire qui vous permet d'utiliser l'interpréteur ou le compilateur hôte pour évaluer le code LISP au moment de l'exécution, y compris le code LISP généré au moment de l'exécution. Les descendants de LISP incluent Scheme et Clojure. Dans tous ces langages, la métaprogrammation est le plus souvent vue sous la forme de programmes qui se modifient eux-mêmes, généralement à l'aide de macros.

Dans les années 1970, Robin Milner a développé un MetaLanguage (ML) qui a évolué pour devenir la famille ML de langages de programmation qui inclut Standard ML et OCaml et a fortement influencé Haskell et F # . Ces langues facilitent l'expression d'autres langues. Dans ces langages, les métaprogrammes sont le plus souvent vus sous la forme de lexers, d'analyseurs, d'interprètes et de compilateurs.

En 1994, Erwin Unruh a découvert que le système de modèles C ++ était Turing complet et pouvait être utilisé pour exécuter des programmes arbitraires au moment de la compilation . La métaprogrammation de modèles C ++ a apporté la métaprogrammation aux masses non lavées qui (ab) l'ont utilisée pour de nombreuses choses différentes, y compris la génération de méthodes numériques dans la bibliothèque Blitz ++ .


33

Eh bien, la métaprogrammation n'est que de la programmation, mais c'est essentiellement "écrire du code qui écrit du code" .

La capacité que vous mentionnez, lorsqu'un programme peut observer et modifier sa propre structure et son comportement s'appelle réflexion et c'est un type de métaprogrammation.

Les langages typés dynamiquement, ont de puissantes fonctionnalités de réflexion d'exécution, rendues possibles par la nature interprétée de ces langages ...

Les langages typés statiques ont également de puissantes techniques de métaprogrammation, par exemple la métaprogrammation de modèle C ++ ...


14

Ce n'est que mon opinion personnelle, qui est probablement la définition la plus libérale de la métaprogrammation.

Je pense que cela comprend:

  1. Génération de code de compilation ou génération de code d'exécution (ou les deux)
  2. Pensée orientée aspect ou programmation orientée aspect
  3. Pensée sèche

Je pense que vous pouvez y arriver en utilisant l'un de ces éléments et en combinaison:

  1. Réflexion
  2. DSL (langues spécifiques au domaine)
  3. Attributs (.NET) ou annotations (Java)
  4. Génériques (.NET / Java)
  5. Modèles (C ++)
  6. method_missing (Rubis)
  7. fermetures / fonctions de première classe / délégués
  8. AOP - Programmation orientée aspect

réponse très concise et réfléchie. m'a donné un bon menu de choses à étudier. Merci!
swyx

6

La métaprogrammation consiste à écrire un programme qui sort un autre programme. C'est quelque chose pour lequel des langages comme Lisp sont vraiment bons. C'est beaucoup plus facile à faire dans un langage qui prend en charge de vraies macros (pas des macros C ++, mais plutôt celles qui peuvent manipuler le code qu'elles produisent) comme Ruby, Lisp, Scheme, etc. que dans un langage comme Java.

Une implémentation consiste à créer un "langage spécifique au domaine" qui est une manière d'améliorer un langage de programmation pour accomplir une tâche spécifique. Cela peut être incroyablement puissant s'il est fait correctement. Ruby on Rails est un bon exemple de ce type de programmation.

Si vous souhaitez explorer cette méthode, consultez la structure et l'interprétation des programmes informatiques qui est l'un des livres fondamentaux couvrant le sujet.


5

La métaprogrammation est l'écriture de programmes informatiques qui écrivent ou manipulent d'autres programmes (ou eux-mêmes) en tant que leurs données, ou qui font une partie du travail au moment de l'exécution qui serait autrement effectué au moment de la compilation. Dans de nombreux cas, cela permet aux programmeurs d'en faire plus dans le même laps de temps qu'il leur faudrait pour écrire tout le code manuellement, ou cela donne aux programmes une plus grande flexibilité pour gérer efficacement de nouvelles situations sans recompilation. ( Source .)

Fondamentalement, il s'agit d'écrire du code qui génère plus de code, qui est exécuté pour atteindre un objectif. Cela se fait généralement soit dans la même langue (en utilisant javascript pour créer une chaîne javascript, puis evalelle) soit pour émettre une autre langue (en utilisant .NET pour créer un fichier batch Windows).


4

wikipedia a un bel article sur le sujet. Il n'est pas nécessaire de faire des modifications à l'exécution pour que quelque chose soit qualifié de métaprogrammation. Par exemple, de nombreuses personnes utilisent des modèles C ++ pour effectuer une métaprogrammation au moment de la compilation.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.