Pourquoi le C est moins puissant que votre langage favori
Lire l'article
·
Voir tous les commentaires
·
Commenter
#
lasts
31.03.10, 05:43.
J’ai toujours trouvé dommage qu’en C, les optimisations ne soient que locales : Il est facile de rajouter une couche d’abstraction pour spécialiser un bout de code avec des macros, mais le gain est limité au programme courant. Passer au cap supérieur et instruire directement le compilateur d’une optimisation possible n’est pas aussi simple que, par exemple, abstraire une fonction d’un bloc de code répétitif.
À mes yeux, il semble y avoir une ambivalence entre le désir d’être explicite (j’écris x.foo et j’ai une bonne idée mentale du code produit par le compilateur) et le désir d’être efficace, c’est à dire de rajouter des optimisations non existante dans le compilateur (ou qu’on suppose non existante.) Avec ton exemple, on perd complètement l’explicite et on obtient quelque chose d’assez boite noire, mais qui "fait le travail."
J’ai envie de penser que les "optimisations" suivantes devaient exister lors des premiers compilateurs (non-optimisants) (bien qu’elles aient probablement toujours été écrites directement) :
#define MUL(x, y) (x) * (y)
#define MUL2(x) (x) << 1
En résumé, je ne suis pas sûr d’apprécier la distance entre ces optimisations de bas niveau et le compilateur (le pré-procésseur et l’assembleur étant placés aux extrêmes), mais ça résume assez bien ma vision du C. C’est un langage assez riche et compliqué, mais il est rugueux : Chaque concept est clairement délimité syntaxiquement, ce qui introduit sa dose de complexité au niveau de la grammaire, mais permet aux programmeurs de s’agripper solidement.
En Scheme, le problème est inverse : Il n’y a pas de rugosité du tout et le programmeur est perdu. Je trouve donc amusant que les macros C, qui sont nettement inférieures aux macros Lisp, aient l’avantage de cette limitation pour la structuration intellectuelle du programmeur. "S’il y a de la magie, elle tient toujours dans ma tête." Le problème n’est donc pas la notation préfixe mais "qu’est-ce qui se passe derrière ?"
D’une certaine manière, je trouve qu’OCaml a hérité de cette rugosité vis à vis des records, des accès aux tableaux et des constructeurs. Et ça m’emmerde à chaque fois que je les utilise. :)
Plutôt que de reciter Lisp et Forth, qui sont des solutions à mon goût à ce problème, mais qui souffrent également de leur solution, voici un lien qui propose d’utiliser des compilateurs orientés "extensions" pour le C : http://pdos.csail.mit.edu/xoc/ .
#
bluestorm
27.03.10, 12:18.
Je m’intéresse assez aux à la question de l’encodage, dans un langage plus bas niveau, des fonctionnalités d’un langage plus haut niveau. C’est un outil qui permet de comparer différents langages entre eux (tant d’un point de vue pratique que théorique : la traduction d’une solution vers une autre est une façon courante pour des chercheurs en langages de programmation de comparer ces solutions). J’ai récemment fait un monologue à ce sujet sur le siteduzéro.
Le point de vue que tu abordes est légèrement différent, puisqu’il est centré sur "le langage bas niveau" : en général, on discute de ce qui se passe quand on change de langage pour avoir des constructions plus haut niveau, et on néglige un peu les irréductibles qui veulent conserver leur langage d’avant, et utiliser quand même un style moderne. Les utilisateurs de C ont ce point de vue et c’est assez intéressant. Par ailleurs, la question de la portabilité est assez évidente quand on en parle, mais je n’y avais pas spécialement pensé avant, merci. Cela dit, au sujet de la portabilité, j’ai l’impression que beaucoup de langages font des choix d’implémentation relativement platform independent, comme une machine virtuelle, un bytecode, ou un langage plus bas niveau (C--, LLVM, ou même directement C), et spécialisent la partie bas niveau seulement dans ces couches là, qui sont plus basses que le C. Bien sûr, il y a quand même des choix qui sont fait très tôt, et la question des pointeurs que tu décris en fait sans doute partie.
Une autre application des études de la traduction langage-langage est l’étude de la méta-programmation à l’intérieur d’un langage donné. Par exemple, on peut considérer une partie de la métaprogrammation des LISP (macros et cie.) comme des éliminations d’abstraction syntaxique.
# rz0
03.04.10, 13:28.
Hum, ouais, avant on écrivait facilement
x << 1au lieu dex * 2. C’est d’ailleurs pas mal resté, dans certains cas. Mais yavait des trucs bien plus gores, genre des macrosREGISTERnqui sont remplacées par des déclarationsregisterselon la machine (ça permettait de classer par priorité les variables à mettre dans des registres ; les suivantes devenaient automatiques).À propos de rugosité, je suis tombé récemment sur un assez vieil (2003) article sur MSDN sur comment rendre le code managé rapide et on peut y lire :
C’est de moins en moins vrai avec l’avénement des compilateurs optimisants modernes, mais il y a toujours une certaine vérité à cela, en ce que l’on peut se donner une vague borne pessimiste sur nos performances, en gros. :p
Après, pour ce qui est d’instruire au compilateur comment effectuer certaines optimisations, euh… je ne vois pas trop où tu veux en venir. Tu peux développer ? Au final, on est limité au niveau langage, on ne peut pas vraiment toucher au-dessous. Que suggères-tu ? À quels langages penses-tu ?