Posté par kantien .
En réponse au journal C++17 est sur les rails.
Évalué à 3.
Dernière modification le 18 mars 2016 à 11:34.
Un des intérêts des macros est de permettre d'étendre la syntaxe du langage, je ne vois pas en quoi c'est un problème de conception. S'il n'y a pas de mécanisme d'extension tu peux moins écrire les choses comme tu veux. Et dans le code d'Eliom (c'est peut-être là que je n'ai pas tout compris) j'ai l'impression que des outils de compilation intégrés au langage sont utilisés. Donc pas de macros mais on utilise des outils propres aux compilateurs pour étendre la syntaxe...
Tu as bien compris, et l'intérêt de passer par des outils propres aux compilateurs pour étendre la syntaxe plutôt que d'utiliser des macros c'est :
uniformiser et simplifier l'écriture d'extension
conserver les gardes-fou du typage statique
Jusqu'à il y a deux ans, pour étendre la syntaxe OCaml on utilisait un pré-processeur camlp4 (ce qui, au fond, est similaire à de la macro) mais c'était chiant à écrire et on se retrouvait avec des tonnes de syntaxes différentes entre les projets : la coopération entre projet était rendue plus compliqué. Avec la nouvelle façon de faire, via ppx, cela se passe au niveau de la manipulation des AST et les extensions sont uniformisées : la coopération est simplifiée et s'est accrue. Par exemple dans le cas de Eliom :
letfx=x+1(* définition usuelle d'une fonction en ocaml, ici le successeur *)let%clientfx=x+1(* extension de syntaxe pour dire que cette fonction est définie côté client *)let%serverfx=x+1(* la même mais définie côté serveur *)let%sharedfx=x+1(* elle est accessible aussi bien côté serveur que côté client *)
Étendre la syntaxe d'un langage est une chose fort utile, mais il ne faut pas que cela défigure complètement la syntaxe initiale (ce qui est tentant avec les macros) et quitte à générer du code par modification de la syntaxe autant le faire au niveau de l'AST : ce que montre la signature du foncteur que tu cites (une signature en OCaml c'est l'équivalent des headers en C ou C++, et un foncteur est proche des templates du C++ : une fonction dont les paramètres sont des modules, i.e. des structures ayant une signature donnée).
Les foncteurs (comme les templates en C++) est aussi une manière beaucoup plus simple et sécurisée (meilleur contrôle du typage) de générer du code. Un exemple simple, en OCaml, et la cas de la structure d'ensemble : pour construire des ensembles sur un type de donné quelconque, il suffit de le munir d'une relation d'ordre et d'utiliser le foncteur Set.Make
(* on définit une structure d'ordre sur les entiers *)moduleIntOrd=structtypet=intletcompare=Pervasives.compare(* c'est une fonction d'ordre générique sur n'importe quel type *)end(* on la passe en arguments au foncteur Set.Make *)moduleIntSet=Set.Make(IntOrd)(* et cela génère automatiquement toutes ces fonctions *)moduleIntSet:sigtypeelt=inttypet=Set.Make(IntOrd).tvalempty:tvalis_empty:t->boolvalmem:elt->t->boolvaladd:elt->t->tvalsingleton:elt->tvalremove:elt->t->tvalunion:t->t->tvalinter:t->t->tvaldiff:t->t->tvalcompare:t->t->eltvalequal:t->t->boolvalsubset:t->t->boolvaliter:(elt->unit)->t->unitvalfold:(elt->'a->'a)->t->'a->'avalfor_all:(elt->bool)->t->boolvalexists:(elt->bool)->t->boolvalfilter:(elt->bool)->t->tvalpartition:(elt->bool)->t->t*tvalcardinal:t->eltvalelements:t->eltlistvalmin_elt:t->eltvalmax_elt:t->eltvalchoose:t->eltvalsplit:elt->t->t*bool*tvalfind:elt->t->eltvalof_list:eltlist->tend(* que je peux utiliser dans la foulée *)lete=IntSet.empty(* e est l'ensemble vide *)lete=IntSet.add1e(* je lui ajoute l'élément 1 *)(* je teste si 1 est élément de l'ensemble *)InSet.mem1e-:bool=true
Pour ce qui est du parenthésage, c'est une question de goût, mais la syntaxe de Lisp qui colle à la syntaxe du lambda-calcul n'est pas toujours des plus simples à lire. Par exemple la fonction qui consiste à échanger l'ordre d'application des arguments d'une fonction s'écrit en \lambda-calcul : \lambda z.(\lambda x.(\lambda y.(z y)x)), là où je trouve la syntaxe let swap z x y = z y x plus « parlante » et moins « lourde ».
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: C'est bien dommage
Posté par kantien . En réponse au journal C++17 est sur les rails. Évalué à 3. Dernière modification le 18 mars 2016 à 11:34.
Tu as bien compris, et l'intérêt de passer par des outils propres aux compilateurs pour étendre la syntaxe plutôt que d'utiliser des macros c'est :
Jusqu'à il y a deux ans, pour étendre la syntaxe OCaml on utilisait un pré-processeur
camlp4(ce qui, au fond, est similaire à de la macro) mais c'était chiant à écrire et on se retrouvait avec des tonnes de syntaxes différentes entre les projets : la coopération entre projet était rendue plus compliqué. Avec la nouvelle façon de faire, viappx, cela se passe au niveau de la manipulation des AST et les extensions sont uniformisées : la coopération est simplifiée et s'est accrue. Par exemple dans le cas de Eliom :Étendre la syntaxe d'un langage est une chose fort utile, mais il ne faut pas que cela défigure complètement la syntaxe initiale (ce qui est tentant avec les macros) et quitte à générer du code par modification de la syntaxe autant le faire au niveau de l'AST : ce que montre la signature du foncteur que tu cites (une signature en OCaml c'est l'équivalent des headers en C ou C++, et un foncteur est proche des templates du C++ : une fonction dont les paramètres sont des modules, i.e. des structures ayant une signature donnée).
Les foncteurs (comme les templates en C++) est aussi une manière beaucoup plus simple et sécurisée (meilleur contrôle du typage) de générer du code. Un exemple simple, en OCaml, et la cas de la structure d'ensemble : pour construire des ensembles sur un type de donné quelconque, il suffit de le munir d'une relation d'ordre et d'utiliser le foncteur
Set.MakePour ce qui est du parenthésage, c'est une question de goût, mais la syntaxe de Lisp qui colle à la syntaxe du lambda-calcul n'est pas toujours des plus simples à lire. Par exemple la fonction qui consiste à échanger l'ordre d'application des arguments d'une fonction s'écrit en \lambda-calcul : \lambda z.(\lambda x.(\lambda y.(z y)x)), là où je trouve la syntaxe
let swap z x y = z y xplus « parlante » et moins « lourde ».Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.