Par contre la macro est évaluée au moment de la compilation, donc une seule fois.
Il reste juste à noter que cette macro est assez simple mais qu'elle pourrait faire des calculs complexes, parcourir les expressions qu'on lui passe en paramètre (il s'agit de simples listes), faire n'importe quoi pour générer le code Lisp destiné à la remplacer. Il s'agit simplement de code Lisp quelconque manipulant des listes (parcours, construction, ...).
Est-ce que c'est plus clair ?
Oui c'est plus clair, je n'avais pas fait attention à ta remarque qui expliquait que les macros étaient exécutées à la compilation (ce qui explique leur dénomination).
En fait le compilateur OCaml fait la même chose avec certaines fonctions, et dans la nouvelle version à venir il le généralise via une nouvelle représentation intermédiaire, qui ne sera qu'optionnelle pour cette version, mais sera sans aucun doute la base pour les versions ultérieures. Par exemple le compilateur actuel remplace systématiquement les appels à ma fonction iff par if b then e1 else e2 (comme si c'était une macro en Common Lisp), mais le nouveau système pousse l'idée plus loin en l'étendant aux fonctions récursives et en « exécutant » au maximum le code de la fonction qu'il développe. Tu pourras en lire plus sur la partie que j'ai consacré, avec chicco, au système FLambda dans la dépêche en cours de rédaction.
Sinon if est aussi une primitive en OCaml, comme en Common Lisp, mais n'est en fait qu'un cas particulier d'une autre structure primitive le pattern matching qui est une version généralisée de ta macro cond : if b then e1 else e2 n'est qu'un alias pour match b with true -> e1 | false -> e2, et on peut mettre autant de cas que l'on veut dans l'analyse et pas seulement en faisant des tests sur les booléens mais sur la forme et la structure du type que l'on étudie. Cela parce que, comme pour Common Lisp, toutes les valeurs sont essentiellement des références (sauf les types int, bool, char et les constructeurs constants comme la liste vide) et accessible uniquement via leur constructeur de type.
Par exemple pour définir la fonction list_map qui applique une fonction à tous les éléments d'une liste, on l'écrira
(* en OCaml le type des listes se définit comme *)type'alist=|Nil(* la liste vide *)|Consof'a*'alist(* le nom du constructeur est issu du nom de l'opérateur en Lisp ;-) *)(* [] est un alias pour la liste vide et hd :: tl un alias pour Cons(hd, tl) la liste [1; 2; 3] se construit par Cons(1, Cons(2, Cons(3, Nil))) et on retrouve la structure de liste imbriquée à la Lisp *)letreclist_mapfl=matchlwith(* soit la liste est vide et on renvoie la liste vide *)|[]->[](* soit elle a une tête et une queue, alors on applique f à la tête et list_map à la queue *)|hd::tl->(fhd)::(list_mapftl);;(* on peut alors faire une fonction qui renvoie la liste des successeurs d'une liste d'entiers *)letsucc_listl=list_map(funn->n+1)l;;(* mais à la compilation il va développer list_map comme une macro et simplifier le tout en *)letsucc_listl=letreclist_map'l=matchlwith|[]->[]|hd::tl->(hd+1)::(list_map'tl)inlist_map'l;;
Sinon pour la coloration de code en Common Lisp, je mets lisp comme langage.
[^] # Re: C'est bien dommage
Posté par kantien . En réponse au journal C++17 est sur les rails. Évalué à 1.
Oui c'est plus clair, je n'avais pas fait attention à ta remarque qui expliquait que les macros étaient exécutées à la compilation (ce qui explique leur dénomination).
En fait le compilateur OCaml fait la même chose avec certaines fonctions, et dans la nouvelle version à venir il le généralise via une nouvelle représentation intermédiaire, qui ne sera qu'optionnelle pour cette version, mais sera sans aucun doute la base pour les versions ultérieures. Par exemple le compilateur actuel remplace systématiquement les appels à ma fonction
iffparif b then e1 else e2(comme si c'était une macro en Common Lisp), mais le nouveau système pousse l'idée plus loin en l'étendant aux fonctions récursives et en « exécutant » au maximum le code de la fonction qu'il développe. Tu pourras en lire plus sur la partie que j'ai consacré, avec chicco, au système FLambda dans la dépêche en cours de rédaction.Sinon
ifest aussi une primitive en OCaml, comme en Common Lisp, mais n'est en fait qu'un cas particulier d'une autre structure primitive le pattern matching qui est une version généralisée de ta macrocond:if b then e1 else e2n'est qu'un alias pourmatch b with true -> e1 | false -> e2, et on peut mettre autant de cas que l'on veut dans l'analyse et pas seulement en faisant des tests sur les booléens mais sur la forme et la structure du type que l'on étudie. Cela parce que, comme pour Common Lisp, toutes les valeurs sont essentiellement des références (sauf les typesint,bool,charet les constructeurs constants comme la liste vide) et accessible uniquement via leur constructeur de type.Par exemple pour définir la fonction
list_mapqui applique une fonction à tous les éléments d'une liste, on l'écriraSinon pour la coloration de code en Common Lisp, je mets lisp comme langage.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.