5 votes

Variance sémantique dans la langue

J'ai pensé à faire mon propre langage (aspect pratique : c'est une expérience de pensée). Une des idées qui m'est venue est la variation sémantique dans le langage. Vous écrivez essentiellement des expressions régulières sémantiques, qui sont remplacées par du code équivalent. Vous pouvez voir cela sous une forme un peu moins directe dans D - ils ont des mixins string qui convertissent en code D. Sauf que j'allais le faire implicitement, et d'une manière plus circulaire.

Pour l'instant, je suis originaire du C++. Donc si vous considérez :

string a, b, c, d;
// do stuff
a = b + c + d;

Ce code donne lieu à diverses temporalités. Même si vous avez des références rvalue, vous créerez des temporaires, ils seront simplement réutilisés de manière plus efficace. Mais ils existent toujours et gaspillent les performances. Je pensais, dans le cas le plus simple, à la façon dont ils pourraient être éliminés. Vous pourriez écrire une expression régulière sémantique qui les convertirait dans la forme la plus optimisée.

string a, b, c, d;
// do stuff
a.resize(b.size() + c.size() + d.size());
a = b; a += c; a += d;

Si j'implémentais std::string, je pourrais écrire quelque chose d'encore plus rapide. La clé est qu'ils sont implicites - lorsque vous utilisez la classe std::string, les axiomes écrits par l'implémenteur de std::string peuvent affecter tout code std::string. Vous pouvez simplement l'intégrer dans une base de code C++ existante, recompiler et obtenir gratuitement la concaténation de chaînes la plus rapide que votre implémenteur std::string puisse concevoir.

Pour l'instant, les optimisations que vous pouvez faire sont limitées, car vous ne disposez que du contexte que le langage vous permet, dans ce cas, la surcharge des opérateurs en C++ ne prenant que deux arguments, this et arg. Mais un reg ex sémantique pourrait prendre pratiquement tout le contexte dont vous pourriez avoir besoin - puisque vous pouvez dicter ce qu'il correspond - et même correspondre à des caractéristiques du langage qui n'existent pas dans le langage hôte. Par exemple, il serait trivial d'échanger

string a;
a.size;

pour

string a;
a.size();

si vous vouliez voler des propriétés C#. Vous pourriez faire correspondre les définitions de classe et implémenter la réflexion à la compilation ou à l'exécution, etc.

Mais, je veux dire, ça pourrait être confus. S'il y avait un bug, ou si ce qui était réellement fait dans les coulisses ne reflétait pas le code écrit, ce pourrait être une vraie corvée de recherche, et je n'ai pas réfléchi en profondeur à la manière dont cela serait mis en œuvre. Que pensez-vous de la fonction de langage que je propose ?

Oh mec, choisir les bons tags. Ummm....

Edit : Je voulais aussi dépasser les limites, par rapport à une réponse que j'ai eue. Le fait est que la regex sémantique n'a pas de limites (à l'exception des détails d'implémentation qui peuvent devoir être ajoutés). Par exemple, vous pourriez transformer l'expression

int i;
cin >> i;
int lols[i];

sur

int i;
cin >> i;
std::variable_array<int>(alloca(sizeof(int) * i), i);

La sémantique d'alloca rend la manipulation avec des templates impossible - vous devez écrire une macro si vous voulez ce qui précède. En C++03 ou C++0x, vous ne pouvez pas encapsuler vos propres VLA.

En outre, les regex sémantiques peuvent faire correspondre du code qui n'invoque en fait aucun travail de compilation. Par exemple, vous pourriez faire correspondre chaque membre d'une définition de classe et l'utiliser pour créer un système de réflexion. Ceci est également impossible en C++ à ce jour.

1voto

Jerry Coffin Points 237758

Si vous recherchez sur Google quelque chose comme "modèle d'expression C++", vous constaterez qu'en réalité, le C++ possède déjà des capacités assez similaires. En fonction de ce que vous avez trouvé comme syntaxe, votre idée pourrait rendre ce type de code plus facile à comprendre (les modèles d'expression certainement ne sont pas triviales) mais, du moins pour moi, il n'est pas tout à fait clair que vous ajoutez beaucoup (si tant est qu'il y ait quelque chose) en termes de capacité véritablement nouvelle.

1voto

(Avertissement : réponse de mammouth en perspective !)

Je crois que cela s'appelle une macro ;) Du moins, en dehors du monde C/C++ (où "macro" fait référence à cette substitution très limitée que fournit le préprocesseur). Et ce n'est pas très nouveau. Bien que je pense qu'un système de macro approprié et puissant peut ajouter plus de puissance à un langage que n'importe quelle autre fonctionnalité (étant donné que nous préservons suffisamment de primitives pour que ce ne soit pas simplement turing-complet, mais utile pour la programmation réelle), dans la mesure où un programmeur suffisamment intelligent peut ajouter presque toutes les fonctionnalités qui pourraient s'avérer utiles à l'avenir ou pour un domaine spécifique sans ajouter de règles (supplémentaires) au langage.

L'idée de base est d'analyser un programme en une représentation au-dessus d'une chaîne de caractères avec le code source, disons un AST ou un analyser l'arbre . De tels arbres fournissent plus d'informations sur le programme, et un autre programme peut parcourir cet arbre et le modifier. Par exemple, il serait possible de rechercher un fichier VariableDeclaration vérifiez s'il déclare un bon vieux tableau de T et le remplacer par un nouveau VariableDeclaration qui déclare à la place un std::variable_array de T . On peut par exemple l'affiner en fournissant une correspondance de motifs pour l'arbre, ce qui facilite la métaprogrammation. Une procédure puissante, si et seulement si le programmeur peut faire face à ce niveau d'abstraction et sait en faire bon usage.

Notez que lorsque je parle de "filtrage", je parle du filtrage de la programmation fonctionnelle, et non des expressions régulières. Les expressions régulières sont insuffisantes pour donner un sens aux langages irréguliers, ce qui inclut à peu près tous les langages utiles - le simple fait d'autoriser les expressions de taille abritante, y compris les parenthèses équilibrées, exclut les expressions régulières. Voir la réponse acceptée sur Qu'est-ce que le "Pattern Matching" dans les langages fonctionnels ? pour une excellente introduction au pattern matching, et peut-être apprendre un langage fonctionnel comme Haskell ou O'Caml, ne serait-ce que pour apprendre à l'utiliser et à traiter les arbres (et il y a une tonne d'autres fonctionnalités sympas !).

Maintenant sur le langage que vous proposez : Honnêtement, je doute qu'il soit utile. Le C++ lui-même est un exemple parfait de comment ne pas concevoir un langage (à moins que vous ne vouliez réussir) : Prendre un langage existant, rester rétro-compatible = tout garder (y compris les mauvaises choses), et ajouter un tas de nouvelles fonctionnalités qui sont assez complexes en elles-mêmes, puis les modifier un millier de fois et ajouter une centaine de cas spéciaux pour travailler plus ou moins avec la syntaxe et la sémantique du langage existant. Cela rend le succès plus probable (si le langage avec lequel vous avez commencé est déjà populaire), mais vous vous retrouvez avec une bête obscure et inélégante. Ceci étant dit, j'aimerais vraiment voir un langage non-lisp qui permette des macros d'une telle puissance.

La bonne (ou du moins, la meilleure) façon de procéder serait de repenser chaque élément, de la sémantique la plus élémentaire à la syntaxe exacte, de l'intégrer à ce que vous voulez ajouter et d'ajuster toutes les parties du nouveau langage jusqu'à ce que l'ensemble soit parfait. Dans votre cas, cela aurait extrêmement effet secondaire pratique : la facilité d'analyse. Bien sûr, le source doit être analysé avant que les macros puissent être appliquées, puisqu'elles s'intéressent à un arbre, et non à des fragments de chaîne. Mais le C++ est très difficile à analyser. Comme, littéralement, le langage le plus difficile à analyser dans l'usage courant.

Oh, pendant qu'on y est : Les macros elles-mêmes peuvent rendre la vie de nos outils préférés (IDE avec autocomplétion et conseils d'appel, analyse statique du code, etc. Donner un sens à un morceau de code est déjà assez difficile, mais cela devient encore pire si ce code est transformé de manière abritée, et peut-être très lourdement, avant d'atteindre la forme qui est exécutée. En général, les outils d'analyse de code ne peuvent pas gérer les macros. Tout ce domaine est si difficile que Des gens intelligents inventent de nouveaux langages pour faire des recherches sur le sujet et écrivent des articles qu'aucun d'entre nous ne peut comprendre. Sachez donc que les macros ont des inconvénients.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X