C++ + Java + Python = D [Langage D] - C++ - Programmation
Marsh Posté le 03-12-2005 à 12:28:13
III - Programmation OO et modules
1.Les classes
Les programmeurs Java seront en terrain connu, D reprenant la plupart des (bonnes) idées de Java en POO.
Les spécificités de D :
Voici une petite classe "administrés" en exemple :
Code :
|
Attention : les objets, comme les tableaux, sont créés uniquement sur le tas et passés par référence.
L'instanciation se fait donc uniquement avec l'opérateur new :
Code :
|
2.Les fonctions
Les fonctions et méthodes en D possèdent elles aussi des propriétés intéressantes. Le mot inline n'existe pas, le choix de mettre une fonction en inline ou pas étant a la discrétion du compilateur.
Le passage des paramètres se fait par valeur pour les types de base simple et par référence pour les autres types (tableaux, types structures). L'opérateur & du C++ est supprimé.
De plus les attributs in (attribut par défaut), out, et inout renseignent le compilateur sur les droits de modification des paramètres par la fonction. Les paramètres de type out sont initialisés avec leur valeur par defaut.
Des attributs supplémentaires ont été ajoutés aux déclarations de fonctions par D2 pour permettre une gestion très fine de la sécurité et des performances (ref, pure, @Safe, nothrow). Je ne peux pas les détailler dans une introduction, le lecteur intéressé peut se reporter ici: http://dlang.org/function.html
Les fonctions peuvent être imbriquées, la portée de la fonction imbriquée se limitant a la fonction qui la contient. Par contre, les portées de deux variables locales ayant le même nom ne peuvent se superposer. Ex. :
Code :
|
La syntaxe des pointeurs de fonction est elle aussi rendue plus lisible.
On déclare un pointeur de fonction (sur une fonction statique seulement, càd définie à la compilation) de la façon suivante:
Code :
|
Pour les fonctions non statiques, l'équivalent du pointeur de fonction est le pointeur de fonction déléguée, dont l'usage est similaire. Une fonction déléguée a accès aux variables de la pile dans le contexte à partir duquel elle est appelée.
Code :
|
Mais ce n'est pas fini. Comme en Java, une fonction peut être anonyme. Cela permet certaines fantaisies qui sont normalement du domaine réservé des langages de programmation fonctionnels (même si l'usage reste loin d'être aussi pratique qu'avec ces derniers).
Ainsi, l'exemple du pointeur de fonction peut s'écrire de façon plus directe :
Code :
|
Pour les fonctions déléguées anonymes:
Code :
|
Enfin, à partir de la v2.007, le langage intègre les fermetures.
Les fonctions supportent la programmation par contrat. Ce concept de Bertrand Meyer consiste simplement à faire des vérifications sur les valeurs d'entrée (préconditions)et de sortie (postconditions) de la fonction avec des assert.
Un exemple :
Code :
|
La réflexion sur les invariants de classe et les contrats devrait faire partie intégrante du design et être documentée dans les spécifications détaillées.
Enfin, D les fonctions supportent aussi les nombres variables d'arguments.
3.Les attributs
Les attributs lors de la déclaration de classes et de membres précisent :
On peut attribuer un attribut à plusieurs déclarations en les englobant dans un scope.
Ex.
Code :
|
Les RTTI
D intègre une identification de types comparable à C++.
L'introspection à la compilation est prévue.
5.Les modules
Pour la compilation séparée, D, comme Java, n'utilise pas de .h, mais des modules et des interfaces.
Un module correspond à un fichier (généralement une classe). Le nom du module est déclaré par le mot-clé module.
L'importation d'un module se fait avec le mot-clef import, de la même manière qu'en Java.
La compilation se fait en 2 passes. La première applique les règles de compilation conditionnelle (équivalent d'un preprocessing) et vérifie la syntaxe, la deuxième vérifie le typage et effectue la compilation proprement dite.
Cela a plusieurs avantages :
- les forward déclarations de C++ ne sont plus nécessaires,
- l'absence de .h ajoutée à une syntaxe plus simple à parser que le C++ rend la compilation très rapide, environ 10 fois plus rapide que g++ pour un code équivalent,
- les messages d'erreur sont généralement assez pertinents, car toutes les erreurs de syntaxe sont relevées durant la première passe.
Marsh Posté le 03-12-2005 à 12:28:22
IV - Programmation générique
1.La surcharge d'opérateurs
Beaucoup d'opérateurs sont surchargeables en D, des opérateurs unaires comme binaires, commutatifs ou non. Se référer à la doc pour en connaitre la liste. Les opérateurs ., &&, ||, et l'opérateur ternaire ?: ne sont pas surchargeables.
2.Les templates
Les templates sont des objets paramétrés. C++ tire une grande partie de sa puissance des templates, on peut même dire qu'ils sont l'une des grandes victoires de ce langage. Ils permettent la programmation générique en donnant accès au polymorphisme à la compilation. Les templates C++ sont versatiles et puissants. Malheureusement, la syntaxe des templates est connue pour être particulièrement retorse et nécessite bien souvent de se battre contre le typage du compilateur.
L'implémentation des templates en D tente de remédier aux difficultés syntaxiques de C++ tout en généralisant le modèle. Et comme nous allons le voir elle y arrive remarquablement.
Un template est déclaré ainsi : template nom(T, T1, T2) {...}, et instancié par : nom!(type).
Les paramètres T, T1, T2 peuvent être chacun un type, une valeur d'un type de base ou une variable.
Alors qu'en C++, seules les fonctions et les classes peuvent être paramétrées, en D, le contenu des accolades est une portée dans laquelle on peut mettre à peu près n'importe quoi : classes, structs, types, enums, variables, fonctions, d'autres templates, voire même un programme entier.
Ex.
Code :
|
Dès ce premier exemple, on voit que D se démarque de C++, declPtr n'étant ni une fonction (il n'y a pas de paramètre autre que le type T) ni même une classe, mais une sorte de structure anonyme contenant une variable t de type T*.
Deux instantiations d'un même template avec la même liste de paramètres sont identiques, et ce, même si ces deux instances sont dans différents modules. Ceci est dû au fait que comme en C++, la résolution se fait à la phase d'édition des liens.
Code :
|
Parce que l'instanciation se fait à la compilation, les instances d'un template doivent figurer dans le même module que sa déclaration (sinon, le template n'est pas instancié et il y a un problème à l'édition des liens).
Les templates de D offrent une grande lattitude dans la déclaration des paramètres.
Les arguments peuvent être "pattern matchés" avec la syntaxe T : déclaration(T).
Des exemples seront plus explicites :
Code :
|
Exception, pour les classes, : signifie "dérivé de"
Code :
|
Les templates de classes bénéficient d'une simplification syntactique. Si un template ne définit rien d'autre qu'une (et une seule) classe :
Code :
|
Il peut être aussi écrit plus simplement :
Code :
|
Les templates peuvent être aussi partiellement spécialisés avec un type particulier. Lorsque plusieurs templates sont possibles, le plus spécialisé prime :
Code :
|
... ou bien avec une valeur
Code :
|
mais aussi, grâce à l'utilisation d'alias, avec des noms de variables globales, de modules, de templates.
Ex.
Code :
|
Enfin, les paramètres peuvent avoir un type par défaut.
Code :
|
On voit avec les exemples ci-dessus que toutes sortes de spécialisations de templates sont possibles.
3.Les templates variadiques
Les templates peuvent ainsi avoir un nombre indéterminé de paramètres:
Code :
|
sort:
"Les types des parametres sont (int,long,double)"
4.Métaprogrammation par templates
Comme nombre d'opérations sont effectuées à la compilation, les templates permettent d'effectuer des calculs durant cette étape. C'est utile pour produire des tables précalculées, notamment.
L'exemple qui suit utilise astucieusement le mot-clé static if qui permet d'effectuer de la compilation conditionnelle. L'usage de ce mot-clé et des templates permet des optimisations poussées. Notez les templates imbriqués et fortement récursifs.
Code :
|
Un autre exemple: 99-bottles-of-beer
Pour d'autres exemples bien plus impressionnants, allez voir en page 4 de ce topic. Comme l'essentiel du langage est disponible à la compilation, l'usage des templates est très courant en D.
5.Les mixins
Les mixins permettent d'ajouter le code d'un template à la compilation. C'est l'équivalent de coller le code du template à l'endroit où le mixin est appelé. Les mixins et les interfaces offrent dans de nombreux cas une alternative élégante à l'absence d'héritage multiple.
Le mixin est évalué dans cette portée et non là où il est déclaré. Attention, si un symbole est identique dans le mixin et dans la portée appelante, celle-ci a la priorité.
Code :
|
Un exemple d'utilisation des mixins est l'application de design patterns, comme le singleton:
Code :
|
6.L'exécution de fonctions à la compilation (CTFE)
Sous certaines conditions très restrictives (en gros le comportement doit être parfaitement défini et la fonction calculable à la compilation), des fonctions statiques peuvent être exécutées par le compilateur et non au runtime. Cela peut être utile pour le précalcul de tables mathématiques ou bien la manipulation de chaînes de caractères. On remplace ainsi certaines manipulations traditionnellement réalisées par le préprocesseur en C/C++, mais avec toute les constructions du langage à sa disposition.
Marsh Posté le 03-12-2005 à 14:50:37
V-Les ajouts de D2
La déclaration immutable
D2 ajoute deux déclarations à la sémantique du langage: immutable et const. Elles s'inspirent du mot-clé const de C++, avec des différences sémantiques; se référer à la page en question pour les différences. Ce sujet a été l'un des plus difficiles à définir et à justifié à lui seul le développement d'une version 2 du langage. Globalement, si l'usage de immutable et const en D est un peu plus simple que celui de const en C++, il reste difficile à maîtriser et il n'est pas rare de tomber sur des bugs du compilateur. Il est donc conseillé d'utiliser ces qualificateurs avec modération et à bon escient.
immutable indique qu'un symbole est inmodifiable durant toute l'exécution du programme. Aucune référence vers ce symbole ne pourra en changer la valeur. C'est pratique pour la sécurité comme pour le multithreading: une valeur déclarée immutable peut être partagée sans besoin de synchronisation. Ces propriétés permettent au compilateur d'appliquer des optimisations importantes.
Code :
|
Pour plus de souplesse, immutable peut être utilisé comme constructeur de type.
Code :
|
Cette fois, le qualificateur immutable s'applique au type entre parenthèses, ce qui signifie que la chaîne s[] = "hello" est immutable, mais la référence vers la chaine s ne l'est pas.
Code :
|
La déclaration immutable peut être rajoutée ou supprimée à tout moment à l'aide d'un cast().
Fonctions membres immutables
Une fonction déclarée immutable ne modifie pas les membres de la classe/struct à laquelle elle appartient.
Code :
|
La déclaration suivante est équivalente:
Code :
|
Notez que la valeur de retour n'est pas immutable. Pour cela, il faut écrire:
Code :
|
Marsh Posté le 03-12-2005 à 14:51:00
ReplyMarsh Posté le 03-12-2005 à 19:43:44
intéressant
Marsh Posté le 04-12-2005 à 22:38:39
pkoi ya pas de vraie lib standard ?
Marsh Posté le 04-12-2005 à 22:52:09
en ce qui concerne les classes...
1/ tu as oublier
alias identite personne |
2/ ya pas un problème de nom avec p et *p ??
Marsh Posté le 04-12-2005 à 22:52:19
on pourrait avoir un aspect plus comparatif par rapport aux autres langages ?
parce que dire que ça insiste sur la sécurité et mettre de l'asm inline(par exemple) en même temps qu'un GC, c'est l'échec assuré.
Qu'est-ce qui à conduit les gusses à prétendre faire mieux que ce qui existe actuellement, et en quoi ils estiment avoir réussi ?
Marsh Posté le 04-12-2005 à 22:53:04
Kangol > bien vu, il y en a qui suit
Citation : pkoi ya pas de vraie lib standard ? |
Si il y en a une une, elle s'appelle Phobos. C'est vraie qu'elle pourrait être mieux foutue mais elle est adéquate dans la majorité des cas. Par contre, le manque d'un équivalent d'une vraie STL (pour ne pas dire Boost) se fait sentir, même si les tableaux sont puissants.
Ce qui s'en rapproche le plus est MinTL, mais j'ai des problèmes avec.
Citation : on pourrait avoir un aspect plus comparatif par rapport aux autres langages ? |
Il y a un comparatif sur le site.
Ce qui est plus intéressant, ce n'est pas tellement le tableau, mais les pages D vs C++, qui montrent les simplifications qu'offre le langage par rapport au C++.
Pour ce qui est de la sécurité, le point de référence est le C++ et le Java. Je pense que D est plus proche de Java que de C++ de ce point de vue-là.
Mais l'auteur ne veut pas sacrifier les performances pour autant. La philosophie est que la syntaxe doite être rendue suffisamment simple et un maximum de chausse-trappes et d'ambiguités du C++ supprimées. Mais il est tjrs possible de déconner complètement si on y tient vraiment, mais il faut quasiment le faire exprès. Un truc agréable par rapport qu C++ est que le compilo donne des messages assez bons.
Marsh Posté le 04-12-2005 à 23:35:29
Citation : Mais l'auteur ne veut pas sacrifier les performances pour autant. |
et donc ? c'est quoi le rapport avec la choucroute ? l'asm inline ça fait gagner des perfs ? alors que ça élimine immédiatement toute possibilité d'optimiser, ça bloque des registres et un humain n'a qu'une faible probabilité de faire mieux que le compilo ?
D'autre part, la référence, c'est plus C++ mais C# et java pour la vielle techno, le fonctionnel pour le futur. Ce langage sent la grand-mère.
Marsh Posté le 04-12-2005 à 23:36:29
d'autre part, le mec qui se sent assez malin pour tenter d'optimiser un truc à la main a toutes les chances de foutre la mémoire en l'air.
edit : tiens, fous-ça dans les pattes d'harok, tu vas voir ...
Marsh Posté le 04-12-2005 à 23:38:32
j'ai l'impression que ce truc n'innove pas, et ne transcende pas non plus les compromis de C# et java. Il n'apporte rien de nouveau.
par exemple, les "dynamic closures" sont un truc dangereux en style impératif, on en a discuté ici déjà, y'a un risque de faire péter la pile (ou d'avoir une closure dont lexécution échoue). Pourquoi avoir foutu ça là-dedans ?
ça se justifie en fonctionnel, où la "pureté" est de mise (même en o'caml, on peut pas poser de mutable sur la pile), mais là on court au crash.
Les paramètres out : c'est pas parce Ada a repris des truc débiles qu'il fallait que C# et D fassent pareil.
et j'ai encore d'autres exemples.
Marsh Posté le 04-12-2005 à 23:46:11
je trouve pas les param out debile
l'asm inline, j'aime bien avoir cette possibilité dans ma trousse a outls, perso. je l'utilise une fois tous les 10mois, mais quand meme
Marsh Posté le 04-12-2005 à 23:50:25
nraynaud a écrit : |
nraynaud a écrit : j'ai l'impression que ce truc n'innove pas, et ne transcende pas non plus les compromis de C# et java. Il n'apporte rien de nouveau. |
Le C++ et le Java/C# n'ont quand même pas les mêmes possibilités ni tout-à-fait les mêmes utilisations.
Ce langage ne prétend pas révolutionner le monde, il prétend faire aussi bien ou mieux que le C++ dans son domaine. L'auteur de ce langage a aussi écrit un compilateur C/C++, c'est la référence à battre pour lui.
Marsh Posté le 04-12-2005 à 23:54:13
chrisbk a écrit : je trouve pas les param out debile |
y'en a dans toonaze ? ça m'étonne pas.
et la valeur de retour, c'est pas mieux pour passer des paramètres ?
Marsh Posté le 04-12-2005 à 23:56:25
nraynaud a écrit : y'en a dans toonaze ? ça m'étonne pas. |
non, parce que c'est penible a faire
(donc ta gueule quoi )
nraynaud a écrit : |
ouais bin quand tu veux renvoyer deux trucs, bin t'es zobi ou alors tu fais une classe bidon, ce qui craint du cul
y'a pas long j'ai ecrit ca en C++
Code :
|
bin jtrouve ca pratique, ca fait "retour" d'info optiionel (le factor en question) sans pour autant devoir faire des magouilleries sur le return
d'ailleurs c'est pas des parametres qu'on passe par la valeur de retour, mais une valeur de retour
Marsh Posté le 05-12-2005 à 00:05:31
enfin jdis penible a faire, en fait non ?
suffit de gerer un acces a une var out comme a une variable membre, genre avec une instruction en IL1, genre c+b avec b en out (ou ref):
|
(la propagation de copie nous eliminera la derniere assignation)
au passage en IL2 ca se transformera en
mov sym1, a; |
on passe un coup de propagation d'adresse
Code :
|
un coup de deadcode
Code :
|
et zou
Avec une etude de vie on arrivera a un truc genre
Code :
|
en fait c'est tout con j'aurais pu le faire, et si j'aurais reflechi au pb bin je l'aurais probablement fait Faut juste apres se cogner les analyses de flux pour les lectures avant assignation et les sorties sans assignations merci de m'avoir fait remuer des souvenirs, ca fait plaisir de voir qu'y'en reste deux trois trucs de tout ca
Marsh Posté le 05-12-2005 à 00:07:59
U teh ehll
I don't give a siht to teh suxor out parameter
Marsh Posté le 05-12-2005 à 00:08:58
its because ur too supid to understnad tehir tru power, mroon
Marsh Posté le 05-12-2005 à 00:10:57
de toute facon depuis que je fais de l'actionscript j'ai atteinds l'état Zen du programmeur. Plus rien ne peut m'atteindre, je prevois tout a l'avance et tout ce qu'il se passe fait partie de mon Plan
Marsh Posté le 05-12-2005 à 00:55:02
chrisbk a écrit : ouais bin quand tu veux renvoyer deux trucs, bin t'es zobi ou alors tu fais une classe bidon, ce qui craint du cul |
En python on renvoie des tuples et on utilise la magie de l'unpacking en sortie de fonction
(bon par contre tes considérations d'optimisations au cycle près avec ton ASM et tout tu te les fous au cul hein)
Marsh Posté le 06-12-2005 à 12:40:10
nraynaud a écrit : |
J'ai un peu du mal avec ca aussi
Marsh Posté le 08-12-2005 à 13:07:18
ReplyMarsh Posté le 10-12-2005 à 21:43:00
Bon, vu que le topic est en cat C++, je me permet de faire une petite comparaison (simpliste) avec le futur C++0x.
Ce qui apporte quelquechose par rapport au C++, ça me parait etre : inférence de type, gc, programmation par contrat, vrais modules, strong typedef.
- Pour l'inférence de type, c'est prévu pour C++0x. Avec les mots clés auto et decltype.
- Le gc de boehm va etre intégré aussi, avec pas mal de souplesse normalement.
- La programmation par contrat va surement voir le jour aussi, il y a un proposal, mais la façon dont ça va s'intégrer avec les _concepts_ de Gaby et Bjarne, je crois que c'est encore pas fixé ...
- les modules, (parce que je ne considère pas le C++ en ait actuellement), vont également naitre, du moins je l'espère. Il y a un proposal fabuleux la dessus (le dernier en date est de Vandevoorde). Si ça passe, ça occasionnera du boulot pour les developpeurs de compilateurs, puisque export devra etre implémenté.
- le typedef de D, devrait devenir opaque typedef en C++0x.
Les moins :
- L'héritage multiple laissé sur la touche. Au contraire, le C++ pourrait s'enrichir des apports de C++/CLI en matière d'héritage multiple.
Neutre :
- Les dynamiques closures, toussa. Y aura pas en C++0x, sauf erreur. Mais j'avoue que j'en ai jamais vraiment compris l'intérêt
Sinon, question, il n'y a pas d'instanciation implicite de template en D ? J'ai cru voir ça sur le site de digitalmars.
Ce serait quand meme une énorme restriction. Mais ça éviterai les problèmes liés à export, qu'auront à se cogner les implémentations C++.
En bref, par rapport à un éventuel C++0x qui aurait normalisé ce que j'ai indiqué, je ne suis pas convaincu que D lui soit supérieur. Le défaut du C++ auquel on peut s'attendre, c'est que la complexité du langage va croitre fortement. Si D se veut plus simple, c'est clair qu'il n'aura aucun mal Enfin il y a un groupe au WG21 qui s'adonne à rendre le C++ accessible pour les utilisateurs occasionnels
Marsh Posté le 10-12-2005 à 21:45:42
++fab a écrit : |
oscour
Marsh Posté le 10-12-2005 à 22:15:11
Merci pour ta participation, ++fab.
Je l'ai mis en cat C++, car c'est le langage vise par D.
Mes commentaires :
++fab a écrit : - les modules, (parce que je ne considère pas le C++ en ait actuellement), vont également naitre, du moins je l'espère. Il y a un proposal fabuleux la dessus (le dernier en date est de Vandevoorde). Si ça passe, ça occasionnera du boulot pour les developpeurs de compilateurs, puisque export devra etre implémenté. |
A mon avis, c'est pas demain la veille. D'ailleurs D ne le fait pas non plus, vu que les templates doivent etre instancies dans le module qui le definit.
- le typedef de D, devrait devenir opaque typedef en C++0x.
Citation : |
Je ne crois pas que ce soit un gros desavantage. L'heritage multiple est l'un des aspects les plus critiques du C++, et franchement, les (bonnes) occasions de bien les utiliser sont assez rares.
D utilise des interfaces comme en Java, et en plus, utilise les mixins, qui sont des templates avec lesquels on peut faire une sorte d'heritage multiple.
Citation : |
Regarde le paragraphe sur les fonctions et les delegates. J'ai explique.
Citation : |
J'ai pas vu ca, et sauf si on met un type par defaut, je ne vois pas comment ce serait possible. Mais effectivement, l'instantiation est obligatoire. C'est une restriction, mais quand meme largement moins moche que l'obligation de mettre les templates en .h en C++ actuellement, obligation qui a pour effet de multiplier les temps de compilation et casse la separation interface/implementation.
Pour l'export en C++, je leur souhaite effectivement bien du plaisir. Cela signifie que le modele de compilation separee actuel risque d'exploser (mais au fonds, ca n'est pas un mal).
Citation : |
Hmm, le probleme du C++ actuel, c'est justement cette complexite syntaxique.
D reste clair, la ou C++ est et restera fouillis, car :
- D integre par defaut ce qui appartient aux librairies de templates en C++.
- D n'a pas la contrainte d'etre compatible avec du legacy code
- D est relativement orthogonal (les features ne se marchent pas sur les pieds)
Les templates de D sont largement mieux foutus et plus generaux que ceux de C++, qui sont un ajout "tardif" au langage. La nouvelle norme fera elle aussi des ajouts tardifs. C'est mieux que rien, mais ca ne manquera pas de laisser le gout d'un langage bidouille de facon adhoc afin de ne pas trop casser l'existant, la ou D est parti directement sur des bases saines (et modernes) du point de vue de la norme, quitte a se casser la tete pour l'implementation.
Une facon simple de voir cela est de jeter un oeil a la STL et a un equivalent comme MinTL (pas tout-a-fait, mais relativement proche quand meme) en D. D'un cote on a un code proprement imbitable, de l'autre, un code encore hackable par un bon programmeur. Dans la prochaine version de C++, je n'ai pas de doute sur le fait que la STL restera imbitable.
Un autre avantage, ce sont les tableaux, dont la syntaxe est tellement plus agreable que les vector (surtout a n dimensions), et surtout les sous-tableaux.
Enfin, je ne comprends pas que l'initialisation de variables/tableaux ne devienne une feature par defaut comme en D, quitte a la supprimer par un switch du compilo si c'est vraiment necessaire ou mettre un mot-cle adequat ( = void est bien choisi) si on ne veut absolument pas initialiser une variable.
Marsh Posté le 10-12-2005 à 22:17:49
ReplyMarsh Posté le 10-12-2005 à 22:19:13
chrisbk a écrit : oscour |
j'ai rien compris
Marsh Posté le 10-12-2005 à 22:19:34
(cela dit, personne n'est censé aller bidouiller dans la stl)
Marsh Posté le 10-12-2005 à 22:20:35
Dion a écrit : j'ai rien compris |
la seule chose qui a a retenir, c'est ce commentaire des gars de commeau computing, les seuls a avoir implanté le mot clé 'export' de C++. Je fais de tete, en traduisant, mais l'idée est la :
-Qu'est ce que vous conseilleriez a ceux qui veulent implanter export dans leur compilo ?
-Ne pas le faire
Marsh Posté le 10-12-2005 à 22:21:36
Mais euh ca fait koi export machin toussa ?
Marsh Posté le 10-12-2005 à 22:31:36
C'est un peu complique... en gros, ca instancie un template sans vraiment l'instancier.
En fait, ca permet de mettre des templates dans un lobj separee, ce qui n'est pas possible actuellement, parce qu'il faut frocement les instancier pour compiler le code.
Marsh Posté le 10-12-2005 à 22:54:37
chrisbk a écrit : les templates C++ sont ils seulement comparables aux generics de D |
D, ce sont des templates aussi. Tres superieurs a ceux de C++.
Marsh Posté le 11-12-2005 à 10:07:53
quel est l'interet de ce truc ? O_o Qu'apporte t'il de nouveaux par rappot à ce qui existe deja sur le marché (C#, java, C etc...)
Marsh Posté le 11-12-2005 à 10:14:16
Ben lis le topic.
D'une part il compile en natif, d'autre part il reprend ce qu'il y a de mieux dans chacun de ces langages, y ajoute parfois ses propres ameliorations, et les met ensemble dans un tout a peu pres coherent.
L'interet est donc :
- pour les programmeurs C++ de beneficier des avancees syntactiques proposees par Java/C#. Par rapport a C++, D est plus agreable, plus expressif et plus sur.
- pour les programmeurs Java/C# de beneficier de la puissance et de la rapidite de C++ sans les inconvenients et la complexite (Par contre , pour Java, ils perdent en portabilite et en librairies).
- pour les programmeurs C, un langage moderne qui est compatible avec les libs C existantes (mais pas C++).
Marsh Posté le 11-12-2005 à 14:30:38
el muchacho a écrit : Je ne crois pas que ce soit un gros desavantage. L'heritage multiple est l'un des aspects les plus critiques du C++, et franchement, les (bonnes) occasions de bien les utiliser sont assez rares. |
Pas de mon point de vue. sur les 3 principaux idiomes C++, 2 ont recours à l'héritage multiple : les policy classes (Alexandresu), et ...
el muchacho a écrit : D utilise des interfaces comme en Java, et en plus, utilise les mixins, qui sont des templates avec lesquels on peut faire une sorte d'heritage multiple. |
... les mixins, qui ne font pas parti du core langage, mais qui sont aisément faisable à partir d'héritage multiple virtuel.
el muchacho a écrit : Regarde le paragraphe sur les fonctions et les delegates. J'ai explique. |
Oui, j'ai regardé, mais je ne vois pas de révolution par rapport à l'utilisation de boost::lambda, boost::function, ou encore d'un foncteur locale à une fonction.
el muchacho a écrit : |
Et bien le C++ dispose déjà de l'instanciation explicite de template, que tu peux compiler et poser dans un .o. Après, pour avoir l'instanciation implicite - comme c'est le plus élégant - il faut rendre le code template visible pour pouvoir générer du code.
el muchacho a écrit : |
Ben vu qu'il n'y pas d'instanciation implicite de template, et que le C++ dispose déjà de l'instanciation explicite, je vois pas en quoi D est supérieur. Si, éventuellement la possiblité de paramétrer n'importe quelle scope ... mais bon, c'est un avantage mineur par rapport à la restriction précédente.
Pour l'avenir, les templates C++ vont acquérir une puissance assez extra-ordinaire, notament grâce à l'inférence de type et la notion de "concept" pour définir le contrat que doit respecter un paramètre générique, et permettre au compilo de donner un message d'erreur clair.
Dans la pratique, à quoi sert ceci : template Foo( T : A ) {} ?
Est-ce à forcer T à implémenter l'interface de A ? Si oui, c'est cette problématique que les "concepts" vont résoudre plus élégament.
Autre chose, est-ce que l'averload de fonction template fonctionne de la meme maniere qu'en C++ ?
el muchacho a écrit : Une facon simple de voir cela est de jeter un oeil a la STL et a un equivalent comme MinTL (pas tout-a-fait, mais relativement proche quand meme) en D. D'un cote on a un code proprement imbitable, de l'autre, un code encore hackable par un bon programmeur. Dans la prochaine version de C++, je n'ai pas de doute sur le fait que la STL restera imbitable. |
enlève les __ en préfix, et c'est tout de suite moins imbitable
el muchacho a écrit : Un autre avantage, ce sont les tableaux, dont la syntaxe est tellement plus agreable que les vector (surtout a n dimensions), et surtout les sous-tableaux. |
un avantage à avoir les tableaux dans la partie SL, c'est la possibilité de paramétrer statiquement une classe, un algorithme, ... avec au choix un des conteneurs standards std::vector, std::deque, ou std::list.
el muchacho a écrit : Enfin, je ne comprends pas que l'initialisation de variables/tableaux ne devienne une feature par defaut comme en D, quitte a la supprimer par un switch du compilo si c'est vraiment necessaire ou mettre un mot-cle adequat ( = void est bien choisi) si on ne veut absolument pas initialiser une variable. |
contraintes de performances, chère au C++ :|
Marsh Posté le 03-12-2005 à 12:27:56
I - Introduction
Ressources
II - Eléments du langage
1. Les types de base
2. Les pointeurs
3. Les déclarations
4. Les tableaux
5. Les tableaux associatifs
III - Programmation orientée objets et modules
1. Les classes
2. Les fonctions
3. Les attributs
4. L'identification de types
5. Les modules
IV - Programmation générique
1. La surcharge des opérateurs
2. Les templates
3. La métaprogrammation par templates
4. Les templates variadiques
5. Les mixins
V - Les ajouts de D2
1. Les qualificateurs immutable et const
I - Introduction
Ce topic a pour but de faire découvrir le langage D, un langage qui a pour ambition de faire mieux que le C++ . Pour cela, il allie les atouts du C++ et du Java.
D est :
Un langage orienté objet moderne
- héritage simple avec interfaces (à la Java, pas de .h)
- surcharge de fonctions et d'opérateurs
- tableaux à taille dynamique, sous-tableaux, foreach
- tableaux associatifs et ranges
- delegates, fonctions anonymes
- fermetures
- classes et fonctions imbriquées
- système de templates très puissant qui supporte mixins et tuples
- identification de types a la compilation
- support de tous les types C natifs
- modules (à la Java)
- exceptions (à la Java)
... qui insiste sur la sécurité
- ramasse-miettes générationnel
- variables, tableaux et pointeurs initialisés par défaut
- vérification contre les dépassements de tableaux (débrayable)
- usage des pointeurs limité à l'essentiel (pointeurs sur objets essentiellement)
- vérification des immutables, const et invariants
- programmation par contrat
- tests unitaires
... la performances et la compatibilité
- compilation native à haute performances, compilateurs 32 et 64 bits
- ABI compatible avec celle du C
- DLL (bientôt) supportés
- asm inline possible et plus pratique qu'en C++
En réalité, le titre de ce topic devrait plutôt être C++ + Java < D.
Le but avoué du langage est de faire mieux que le C++ sur le plan de la simplicité et de la sûreté, tout en gardant ses performances et sa puissance expressive. Pour cela, plutôt que de chercher à garder la compatibilite ascendante avec C, D essaye de simplifier la syntaxe au maximum, en supprimant toutes les idiosyncraties associées a C++, et intègre de nombreuses fonctionnalités de la STL directement dans le coeur du langage, sans pour autant l'alourdir par la syntaxe des templates.
Par ailleurs, D ne fait pas appel a un préprocesseur, les fonctionnalités du préproc C (compilation conditionnelle par ex.) étant elles aussi assez astucieusement incluses dans le langage. Cela explique que D possède beaucoup de mots-clés, mais une librairie standard finalement assez simple.
En ce qui concerne les performances, voici un benchmark qui montre que les perfs sont comparables à celles du C++. Les superbes jeux shoot'em up de Kenta Cho, écrits en D avec la lib SDL et OpenGL donnent une bonne idée des possibilités du langage (le source est inclus, je recommande Gunroar et Torus Trooper).
Ressources
La norme et l'implémentation de référence du compilateur dmd se trouvent sur le site http://dlang.org . L'ouvrage de référence pour apprendre D2 est The D Programming Language d'Andrei Alexandrescu, qui a écrit un tutoriel. Notez que ce compilateur est gratuit mais pas libre, seul le front-end (la partie transformant la grammaire du langage en code intermédiaire) l'est. Il existe aussi un front end pour GCC, appele gdc, ainsi qu'un autre pour LLVM, nommé ldc. Ils sont compatibles avec dmd et leur version suit de près celle de dmd, bénéficiant ainsi des évolutions et des corrections de bugs.
Malgré la complexité du langage, la compilation de D est très rapide, le compilateur limitant le nombre de passes contrairement à C++.
De nombreux éditeurs supportent le langage, mais à défaut, une coloration syntaxique pour Java ou C# peut faire l'affaire. Il existe divers IDE supportant plus ou moins bien le langage. Actuellement, le meilleur choix est l'extension pour Visual Studio et l'excellent Code::Blocks. Code::Blocks supporte la syntaxe de D, la complétion en cours de frappe, la recherche des déclarations/implémentations et l'accès instantané aux erreurs de compilation.
Du point de vue des debogueurs, les débogueurs qui supportent l'ancien format de Microsoft (Visual C++ 6 et Windebug) sont supportés. Windebug 5.1 est inclus dans le download officiel. Mais aujourd'hui on aura avantage à utiliser un débogueur spécifique pour le langage qui s'interface correctement avec Code::Blocks ou emacs: Ddbg.
Sous Linux, vous pouvez essayer ZeroBugs.
Mise à jour (fin déc 2012):
- la maintenance de D1 va être maintenant arrêtée.
- D2 est un langage nettement plus complexe que D1, avec de nombreux concepts nouveaux, en particulier la sémantique immutable/const, les @properties et la librairie des ranges, qui sont des containers améliorés. La spec du langage est stable, les évolutions sont sur la stabilisation du compilateur de référence et les librairies. Le compilateur est enfin proche de pouvoir créer des DLL.
- Phobos est maintenant la seule et unique librairie standard, et commence à être assez correcte grâce aux efforts soutenus de la communauté, malgré encore des lacunes importantes.
- l'ouvrage de référence pour apprendre D2 est The D Programming Language d'Andrei Alexandrescu
- la communauté s'agrandit et le langage gagne petit à petit de la reconnaissance, notamment du coté de la communauté C++, qui en a repris certaines idées pour C++11.
Les ressources sont essentiellement les newsgroups d.D et d.D.learn.
Warning: jusqu'au chapitre V, la suite est essentiellement dédiée à D1, qui est déprécié
Bien que la plupart des exemples compileront, les évolutions spécifiques à D2 ne sont pas présentées avant le chapitre V qui lui est dédié. Se référer aux articles du site dlang.org pour ces présentation.
Cette petite introduction a pour but de donner envie d'en savoir plus sur ce langage, en aucun cas d'en fournir une description complète. Pour cela, je vous renvoie à la definition du langage, qui, contrairement à celle de C++, est claire et lisible. Une connaissance de C++ et/ou de Java est utile pour comprendre les concepts exposés.
Ce topic est un "work in progress", vos remarques, erreurs relevées (il y en a), et autres commentaires sont les bienvenus.
Bon, sur ce, on démarre...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
II - Eléments du langage
1.Les types de base
Les types de base numériques sont byte (entier 8 bits), short (16 bits), int (32 bits), long (64 bits), float (32 bits), double (64 bits), real (type flottant le plus grand supporte par la machine, 80 bits sur x86), ainsi que leurs versions non signees ubyte, ushort, uint, etc.
Notons que comme en C/C++, ces types sont natifs. D y ajoute les types complexes cfloat, cdouble et creal.
On accède aux valeurs min/max autorisées par le type grâce aux constantes type.min, type.max. D'autres constantes sont définies. Ainsi, ubyte.min vaut 0 et ubyte.max 255, la taille d'un ubyte est ubyte.sizeof et son alignement est donné par ubyte.alignof. A ces constantes, les types flottants en ajoutent de nombreuses autres comme type.infinity (valeur "infinie" ) ou type.epsilon (plus petit incrément).
Les types de caractères sont char (UTF-8), wchar (UTF-16) et dchar (UTF-32), et peuvent être castés en int.
A cela, D ajoute le type booléen bit ou bool et le type universel void.
2.Les pointeurs
D supporte les pointeurs de la même manière que C++, mais le langage allant dans le sens de la simplification, il offre des facilités qui font qu'en pratique, on s'en sert relativement peu sans risque de perte de performances. Les pointeurs sont initialisés a null.
3.Les déclarations
Les variables sont par défaut toutes initialisées lors de leur déclaration. Cela permet d'éviter toute une classe de bogues réputés être parmis les plus difficiles a detecter (erreurs de logique qui entrainent des comportements "aleatoires" ).
Généralement, cela n'entraine pas de perte de performances, sauf à l'interieur de boucles fortement sollicitantes. Il est possible d'attribuer la valeur void a la déclaration pour éviter cette initialisation par defaut.
La valeur d'initialisation par défaut est donnée par la valeur type.init. Elle est de 0 pour les types entiers, mais de type.nan (Not A Number) pour les flottants, et FF/FFFF/FFFFFFFF pour les types char/wchar/dchar, ceci pour des raisons évidentes de débogage et de mise au point : avec ces valeurs par défaut, le programme fonctionnera incorrectement dès le premier test (ce genre de valeurs par defaut est d'ailleurs souvent recommandé). Elle peut cependant être modifiée si le besoin se fait sentir.
Exemples:
Enfin, le mot-clé auto permet de faire de ne pas spécifier le type d'une variable si son initialisation permet de le deviner sans ambiguité (inférence de type). Par exemple :
Contrairement à un langage comme Ocaml ou Haskell, l'inférence de type n'est pas suffisamment puissante pour se passer complètement des déclarations. Ceci est dû principalement au fait que comme C et C++, le typage de D n'est pas strict. Il reste que l'usage de auto est recommandé car le compilateur contôle mieux le typage et le code source bien plus lisible.
Pour la déclaration de types, D possède les deux mots-clefs typedef (déprécié depuis 2.057) et alias. Ils ressemblent en surface au typedef de C, mais il y a un piège.
En D, typedef définit un nouveau type, qui peut avoir une valeur par defaut, et est vérifié par le compilateur.
alias, lui, est l'equivalent du typedef de C/C++ et se contente de permettre un renommage.
4.Les tableaux
Les tableaux en D sont de deux types : statiques (taille fixe definie a la compilation) ou dynamiques (taille variable).
Les tableaux dynamiques sont comparables au container std::vector du C++, avec des facilités syntaxiques non négligeables.
Qu'ils soient statiques ou dynamiques, les tableaux 1D définissent les propriétés suivantes :
.sizeof : taille occupée en octets
.length : longueur (que l'on peut spécifier pour les tableaux dynamiques)
.ptr : retourne un pointeur sur le début du tableau
.dup : effectue une recopie du tableau et de ses éléments
.reverse : renverse le tableau
.sort : tri
Quelques exemples donneront rapidement une idée de ce que l'on peut faire avec :
Attention au détail qui tue : dans le cas ci-dessus, sub n'est qu'un pointeurs vers des éléments de a. Il n'y a PAS de recopie. L'intérêt est que le compilateur peut vérifier que le pointeur ne sort pas des limites spécifiées dans le sous-tableau. Ainsi, aa et sub peuvent être considérés comme des itérateurs pour a.
La recopie dans un autre tableau se fait ainsi
Quelle est la différence avec une référence vers un sous-tableau ?
Simple : dans le cas d'une recopie, il y a l'operateur [] accollé à droite de l'identifiant et à gauche du signe =, pas dans le cas d'une référence vers un sous-tableau.
Les tableaux, quelque soit le type contenu, peuvent être concaténés avec l'opérateur ~.
5.Les tableaux associatifs
Les tableaux associatifs ont une syntaxe assez simple :
Ils ont les propriétés suivantes :
.size
.length
.keys : retourne un tableau dynamique avec toutes les cles
.values : retourne un tableau dynamique avec toutes les valeurs associees
.rehash : reorganise le tableau associatif pour optimiser les recherches.
Message édité par el muchacho le 01-05-2012 à 06:31:28
---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien