Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1007 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  [Langage D]C++ + Java + Python = D

 


 Mot :   Pseudo :  
 
 Page :   1  2  3  4  5  6  7  8  9  10
Page Précédente
Auteur Sujet :

[Langage D]C++ + Java + Python = D

n°1258019
el muchach​o
Comfortably Numb
Posté le 03-12-2005 à 12:27:56  profilanswer
 


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. :jap:
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:

Code :
  1. char c; // c est initialise a FF par defaut;
  2. int i = void; // variable non initialisee;
  3. float *ptr; // initialise a null
  4. ubyte a, *b; // interdit, deux types differents doivent être sur deux lignes distinctes
 

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 :

Code :
  1. static x = 3;    // x de type int
  2. auto y = 4u;    // y de type uint
  3. auto s = "string"w; // s de type wchar[6]
  4. class C { ... }
  5. auto c = new C();  // c est une instance de la class C


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.

Code :
  1. typedef int myint = 7;
  2. void foo(int x) { return x+1; }
  3. void foo(myint x) { return x+2; }
  4. myint b;        // b vaut 7
  5. foo(b);         // appelle foo(myint) et retourne 9


alias, lui, est l'equivalent du typedef de C/C++ et se contente de permettre un renommage.

Code :
  1. alias int myint;
  2. void foo(int x) { return x+1; }
  3. void foo(myint x) { return x+2; } // erreur de compile : redéfinition de fonction
 

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 :

Code :
  1. //declaration
  2. char[7] mot = "truc";      // tableau statique de 7 char, mot.length est defini a la compilation
  3. char[] mot2 = "machin";  // tableau dynamique de 5 char
  4. printf("mot : %d, mot2 : %d", mot.length, mot2.length); // affiche "mot : 7, mot2 : 5"
  5. int[] a = [1,2,3,5]; // tableau dynamique de 4 entiers
  6. int[4][3] b;   //  tableau statique de 4x3 entiers contigus en memoire initialises a 0
  7. int b[4][3];   // autre declaration possible du precedent tableau
  8. int[][5] c;    // tableau de 5 tableaux dynamiques d'entiers.
  9. int[][][] d;   //tableau de pointeurs sur tableaux de pointeurs sur des tableaux d'entiers
  10. // affectation, et references vers sous-tableaux ("slicing" )
  11. int[] aa = a;          // aa est un pointeur qui pointe vers le premier element de a
  12. int[] aa = a[];       // meme chose
  13. int[] sub = a[1..4]; // le pointeur sub pointera vers a[1], a[2] et a[3]
  14. printf("%d ", sub);   // affiche "2 3 5"


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

Code :
  1. int[] a = [1:3, 5, 6]; // 1:3 signifie "valeur 3 à l'index 1", contient [0,3,5,6]
  2. int[] copie;
  3. // les lignes suivantes sont toutes equivalentes
  4. copie[] = a;  // copie contient [1,2,3,5,6]
  5. copie[] = a[];
  6. copie[] = a[0..length];  // copie de a[0] a a[length-1]
  7. copie[] = a[0..a.length];


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 ~.

Code :
  1. // concatenation
  2. mot2 ~= mot;    // mot2 contient maintenant "machintruc" et mot2.length vaut 10
  3. // traversee
  4. foreach(char c ; mot) {
  5.     printf("%c ", c);          // affiche "t r u c "
  6. }
  7. // traversee en sens inverse
  8. foreach_reverse(char c ; mot) {
  9.     printf("%c ", c);          // affiche "c u r t"
  10. }
 

5.Les tableaux associatifs
Les tableaux associatifs ont une syntaxe assez simple :

Code :
  1. ulong[ char[] ] id_unique; // tableau associatif ayant pour cles des char[] et valeurs des ulong
  2. char[][] noms = ["Bernard", "Francois", "Severine", "Marie-Chantal", "Albert"];
  3. ulong id = 1000000;
  4. foreach(char[] nom; noms)
  5.    id_unique[nom] = id++;       // on remplit le tableau associatif
  6. // on fait une recherche de "Bernard"
  7. ulong *id = "Bernard" in id_unique;
  8. if (id != null) writeln("%l", *id);


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
mood
Publicité
Posté le 03-12-2005 à 12:27:56  profilanswer
 

n°1258020
el muchach​o
Comfortably Numb
Posté le 03-12-2005 à 12:28:13  profilanswer
 

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.

  • D ne connait que l'héritage simple (mais des mécanismes permettent de pallier à cette limitation).
  • Toutes les classes héritent de la classe Object. Elles peuvent aussi dériver d'interfaces.
  • Les opérateurs :: et -> de C++ n'existent pas, ils sont remplacés par . (point) , ce qui uniformise grandement la notation. Le mot clé super permet d'accéder aux membres de la classe mère.
  • Elles sont imbricables. Sauf si elle porte l'attribut static, la classe imbriquée à acces aux membres de la classe qui la contient. Cela permet d'éviter de dériver certaines classes.


Les spécificités de D :

  • Les contructeurs et le destructeur portent les noms this() et ~this(). Si nécessaire, une désallocation explicite peut être définie avec la méthode delete(void *), qui sera appelée après ~this().
  • On peut définir des invariants de classe (programmation par contrat). Les invariants sont des assertions sur les membres qui sont vérifiées après la construction de la classe, juste avant la destruction, ou lors d'appels de membres publics et non static de la classe. La vérification des invariants peut être débrayée par une option du compilateur. Elle ne remplace pas des vérifications réelles sur les données d'entrée du programme, mais sert à vérifier de façon systématique la validité des données en mémoire au cours de l'exécution.
  • Le compilateur est libre d'organiser l'ordre des membres en mémoire comme bon lui semble, mais la propriété .offsetof permet de connaitre l'adresse relative de chaque membre.
  • Tous les objets sont par défaut créés sur le tas sauf si on précède leur déclaration par le mot-clé scope. L'objet créé est alors détruit en sortie de portée.


Voici une petite classe "administrés" en exemple :

Code :
  1. private import std.stdio, std.process;
  2. class identite
  3. {
  4.     char[] nom, prenom;
  5.     ubyte   age;
  6.     invariant {
  7.         assert(age < 130);
  8.         assert(nom.length > 0);
  9.         assert(prenom.length > 0);
  10.     }
  11.     // constructeur
  12.     this(char[] nom, char[] prenom, ubyte age) {
  13.         if (nom.length > 0) this.nom = nom;
  14.         if (nom.length > 0) this.prenom = prenom;
  15.         if (age >= 16 && age < 130) this.age = age;
  16.     }
  17.     ~this(){} // destructeur
  18.     static ulong id_unique;
  19. }
  20. alias identite personne;
  21. class administres
  22. {
  23.     void ajoute(personne p)    // les objets sont toujours passes par reference
  24.     {
  25.         auto nom_complet = p.nom ~ p.prenom; // concatenation
  26.         nom_complet ~= std.string.toString(p.age);
  27.        
  28.         // recherche dans un associative array/hashmap
  29.         ulong *f =  nom_complet in annuaire;
  30.         if (f == null)
  31.            annuaire[nom_complet] = ++id_unique;
  32.         else
  33.             writefln("Cette identite existe deja !" );
  34.     }
  35.     private :
  36.        static ulong id_unique;
  37.        ulong[ char[] ] annuaire; // annuaire des id_uniques
  38. }
  39. int main(char[][] argv)
  40. {
  41.     try{
  42.         auto base = new administres;   // retourne une reference sur base
  43.         auto joe  = new personne("joe", "black", 34);
  44.         auto jack = new personne("jack", "black", 77);
  45.    
  46.         base.ajoute(joe);
  47.         base.ajoute(jack);
  48.         joe.age = 154;    //erreur : l'invariant est violee. Une AssertException est levee.
  49.     }
  50.     catch(Exception) { writefln("Erreur !" ); }
  51.    
  52.     std.process.system("pause" );
  53. }
 

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 :
  1. class truc{ int t; }
  2. ...
  3. truc unTruc;    // attention : déclare une référence nulle
  4. class unObjet = new truc; // instancie un objet truc
  5. unTruc.t = 2;  // erreur : access violation
 


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 :
  1. int bar(int a, out int c){
  2.     c = 3;
  3.     int foo(int b){
  4.         int c;          // interdit : variable deja déclarée
  5.         int abc(){
  6.             return c; // access bar.c
  7.         }
  8. return b + c + abc();
  9.     }
  10.     return foo(3);
  11. }
 

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 :
  1. //pointeur de fonction prenant un int et retournant un int
  2. int function(int i) fp;
  3. void test()
  4. {
  5.     static int a = 7;
  6.     static int foo(int i) { return a + i; }
  7.     fp = &foo;     //fp pointe vers foo
  8. }
  9. void bar()
  10. {
  11.     test();
  12.     auto i = fp(5); // i vaut 12
  13. }
 

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 :
  1. struct Foo {
  2.     int a = 7;
  3.     int bar() { return a; }
  4. }
  5. // joe prend un pointeur de fonction déléguée en paramètre
  6. int joe(int delegate() dg) { return dg() + 1;}
  7. void test()
  8. {
  9.     auto x = 27;
  10.     int bar() { return x; }
  11.     Foo f;
  12.     int i;
  13.     i = joe(&bar); // i vaut 28
  14.     i = joe(&f.bar); // i vaut 8
  15. }
 

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 :
  1. //pointeur de fonction prenant un int et retournant un int
  2. int function(int i) fp;
  3. void test()
  4. {
  5.     static auto a = 7;
  6.     fp = function int(int i) { return a + i; }
  7. }
  8. void bar()
  9. {
  10.     test();
  11.     auto i = fp(5); // i vaut 12
  12. }


Pour les fonctions déléguées anonymes:

Code :
  1. void test()
  2.     // sommation par la méthode des rectangles
  3.     float integre(float x1, float x2, float step, float delegate(float x) fn)
  4.     {
  5.         auto somme = 0.0;
  6.         for (auto x = x1; x < x2; x += step)
  7.             somme += fn(x1 + (x2-x1)*0.5);
  8.         return somme;
  9.     }
  10.     // intégration de 2 fonctions anonymes
  11.     auto s1 = integre(0.5, 5.0, 0.1,
  12.                  delegate float(float x){ return (x < 1.0) ? 1.0 : 1.0/x; } );
  13.     auto s2 = integre(3.0, 10.0, 0.2,
  14.                  delegate float(float x){ return x*x - 3.0*x + 0.2; } );
  15. }
 

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 :
  1. int foo()
  2. in { ...preconditions... }
  3. out (result) { ...postconditions... }
  4. body
  5. {
  6.     ...implementation...
  7.     if (...)
  8.         return bar();
  9.     return 3;
  10. }


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 :

  • la constance : const
  • l'encapsulation : public, protected, private, package, export. Un membre "package" est accessible par tous les modules appartenant au même package. L'attribut export rend un membre accessible à l'extérieur de l'exécutable, pour une librairie par ex.
  • l'héritage : static (pas d'héritage, données statiques), final (dérivation interdite), abstract (dérivation obligatoire par une classe concrète), override,
  • l'édition des liens : extern
  • l'alignement dans une structure, pour la compatibilité avec les structures C : align
  • la maintenance: deprecated. Un membre deprecated produira un message d'erreur à la compilation s'il est utilisé.

On peut attribuer un attribut à plusieurs déclarations en les englobant dans un scope.
Ex.

Code :
  1. deprecated {
  2.    int toto;
  3.    float foo();
  4. }
 

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.


Message édité par el muchacho le 23-12-2011 à 09:41:03
n°1258021
el muchach​o
Comfortably Numb
Posté le 03-12-2005 à 12:28:22  profilanswer
 

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 :
  1. // déclare une un pointeur du type de l'argument
  2. template declPtr(T) { alias T* t; }
  3. ...
  4. declPtr!(int).t x; // déclare x comme étant de type int*
  5. alias declPtr!(int) abc;
  6. abc.t y; // déclare y comme étant de type int*


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 :
  1. template TFoo(T) { T f; }
  2. alias TFoo(int) a;
  3. alias TFoo(int) b;
  4. ...
  5. a.f = 3;
  6. assert(b.f == 3); // a et b réfèrent à la même instance de TFoo


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 :
  1. template TFoo(T : T*) { }  // Tfoo prend un pointeur vers un T en argument
  2. alias TFoo!(char*) Foo3;    // T est déduit être un char
  3. template TBar(D, U : D[]) { }// U est un tableau du type de D
  4. alias TBar!(int, int[]) Bar1;   // D est un int, U est un int[]
  5. alias TBar!(char, int[]) Bar2; // erreur, D est à la fois un char et un int
  6. template TBar(D : E*, E) { }
  7. alias TBar!(int*, int) Bar3;    // (1) E est un int
  8.                                      // (3) D est un int*


Exception, pour les classes, : signifie "dérivé de"

Code :
  1. class A { }
  2. class B : A { }
  3. template TFoo(T : A) { } // si T est une classe, T est dérivé de A
  4. alias TFoo!(B) Foo4;  // T est un objet B : A
  5. template TBar(T : U*, U : A) { } //T est un pointeur sur un objet B : A
  6. alias TBar!(B*, B) Foo5;  // T est un B*, U est un B
 

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 :
  1. template Bar(T)
  2. {
  3.     class Bar
  4.     {
  5. T member;
  6.     }
  7. }


Il peut être aussi écrit plus simplement :

Code :
  1. class Bar(T)
  2. {
  3.     T member;
  4. }


Les templates peuvent être aussi partiellement spécialisés avec un type particulier. Lorsque plusieurs templates sont possibles, le plus spécialisé prime :

Code :
  1. template TFoo(T)        { ... } // #1
  2. template TFoo(T : T[])  { ... } // #2
  3. template TFoo(T : char) { ... } // #3
  4. template TFoo(T,U,V)    { ... } // #4
  5. alias TFoo!(int) foo1;        // instancie #1
  6. alias TFoo!(double[]) foo2;    // instancie #2 avec T qui est un double
  7. alias TFoo!(char) foo3;        // instancie #3
  8. alias TFoo!(char, int) fooe;   // erreur, nombre d'arguments incorrect
  9. alias TFoo!(char, int, int) foo4; // instancie #4


... ou bien avec une valeur

Code :
  1. template foo(U : int, int T : 10) { //spécialisation pour un entier T qui vaut 10
  2.     U x = T;
  3. }
  4. void main() {
  5.     assert(foo!(int, 10).x == 10);
  6. }


mais aussi, grâce à l'utilisation d'alias, avec des noms de variables globales, de modules, de templates.
Ex.

Code :
  1. import std.string;
  2. template Foo(alias X)
  3. {
  4. alias X.toString y;
  5. }
  6. void test()
  7. {
  8.     alias Foo!(std.string) bar; //spécialisation par un nom de module
  9.     bar.y(3); // appelle std.string.toString(3)
  10. }
 

Enfin, les paramètres peuvent avoir un type par défaut.

Code :
  1. template Foo(T, U = char) { ... } // char est le type par défaut du paramètre U
  2. Foo!(uint,long); // instancie Foo avec T comme uint, et U comme long
  3. Foo!(uint);  // instancie Foo avec T comme uint, et U comme char
  4. template Foo(T, U = T*) { ... }
  5. Foo!(uint);  // instancie Foo avec T comme uint, et U comme uint*
 

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 :
  1. void printType(P...)(P p)
  2. {
  3.     writefln("Les types des parametres sont ", typeid(P));
  4. }
  5. printType(3, 7L, 6.8);


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 :
  1. // Transforme un int en string à la compilation
  2. template int2str(int n)
  3. {
  4.     template digit2str(int n)
  5.     {
  6.   static if (n==0) const char [] s="0";
  7.   else static if (n==1) const char [] s="1";
  8.   else static if (n==2) const char [] s="2";
  9.   else static if (n==3) const char [] s="3";
  10.   else static if (n==4) const char [] s="4";
  11.   else static if (n==5) const char [] s="5";
  12.   else static if (n==6) const char [] s="6";
  13.   else static if (n==7) const char [] s="7";
  14.   else static if (n==8) const char [] s="8";
  15.   else const char [] s="9";
  16.     }
  17.     static if (n<0) const char [] s = "-" ~ int2str!(-n).s;
  18.     else static if (n<10) const char [] s = digit2str!(n).s;
  19.     else const char [] s = int2str!(n/10).s ~ digit2str!(n%10).s;
  20. }
  21. template ordinal(int n)
  22. {   
  23.     static if (n==1)
  24.     const char[] ord = int2str!(n).s ~"er";
  25.     else static if (n==2)
  26.     const char[] ord = int2str!(n).s ~"nd";
  27.     else const char[] ord = int2str!(n).s ~"e";
  28. }
  29. // Calcul de Fibonacci à la compilation
  30. template fib(int n)
  31. {
  32.      static if (n==0)      const int f=0;
  33.      else static if (n==1) const int f=1;
  34.      else                  const int f = fib!(n-1).f + fib!(n-2).f;
  35.      static if (n>0) {
  36.         pragma(msg, "Le " ~ ordinal!(n).ord ~
  37.            " nombre de Fibonnacci est "~ int2str!(fib!(n-1).f).s);
  38.      }
  39. }
  40. int main()
  41. {
  42.     return fib!(30).f;
  43. }


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 :
  1. template Foo(T){
  2.     T x = 5;
  3. }
  4. mixin Foo!(int);
  5. struct Bar{
  6.     mixin Foo!(int);
  7. }
  8. void main(){
  9.     printf("x = %d\n", x);  // prints 5
  10.     {   Bar b;
  11. int x = 3;
  12. printf("b.x = %d\n", b.x); // prints 5
  13. printf("x = %d\n", x);  // prints 3
  14. {
  15.     mixin Foo;
  16.     printf("x = %d\n", x); // prints 5
  17.     x = 4;
  18.     printf("x = %d\n", x); // prints 4
  19. }
  20. printf("x = %d\n", x);  // prints 3
  21.     }
  22.     printf("x = %d\n", x);  // prints 5
  23. }
 

Un exemple d'utilisation des mixins est l'application de design patterns, comme le singleton:

Code :
  1. template Singleton() {
  2.    protected static typeof(this) _instance;
  3.    protected this() { }
  4.    public static typeof(this) instance() {
  5.        if (!_instance) {
  6.             _instance = new typeof(this)();
  7.        }
  8.        return _instance;
  9.    }
  10. }
  11. // Utilisation
  12. class MySingletonClass {
  13.      mixin Singleton!();
  14. }
 

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.


Message édité par el muchacho le 20-12-2011 à 10:00:01
n°1258095
el muchach​o
Comfortably Numb
Posté le 03-12-2005 à 14:50:37  profilanswer
 

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 :
  1. immutable pi = 3.1415926536; // pi est inféré de type float
  2. pi = 2.718281828; // erreur, pi est immutable
  3. immutable char[] s = "foo"; // équivalent à: auto s = "foo" qui est aussi immutable
  4. s = "bar"; // erreur, s est immutable
  5. s[0] = 'a'; // erreur, s[0] réfère à une donnée immutable
  6. int foo(int f)
  7. {
  8.    immutable x = f + 1; // évalué à l'exécution
  9.    x = 3; // erreur, x est immutable
  10. }
 

Pour plus de souplesse, immutable peut être utilisé comme constructeur de type.

 
Code :
  1. immutable(char)[] s = "hello";


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 :
  1. s[0] = 'b'; // erreur, s[] est immutable
  2. s = null; // ok, s n'est pas immutable
 

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 :
  1. struct S {
  2.   int x;
  3.   int foo() immutable {
  4.     x = 4; // erreur, x est immutable
  5.     this.x = 4; // erreur, x est immutable
  6.   }
  7. }


La déclaration suivante est équivalente:

Code :
  1. immutable  int foo() {...}


Notez que la valeur de retour n'est pas immutable. Pour cela, il faut écrire:

Code :
  1. immutable(int) foo() {return 42;}


Message édité par el muchacho le 22-12-2011 à 14:34:15
n°1258096
el muchach​o
Comfortably Numb
Posté le 03-12-2005 à 14:51:00  profilanswer
 

ibidem

n°1258097
verdoux
And I'm still waiting
Posté le 03-12-2005 à 14:52:11  profilanswer
 

Topic mort né, comme ce langage :o

n°1258105
Ace17
Posté le 03-12-2005 à 15:23:41  profilanswer
 

drapeau

n°1258111
chrisbk
-
Posté le 03-12-2005 à 15:38:36  profilanswer
 

y'a malheureusement rien a dire sur ce langage

n°1258182
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 03-12-2005 à 19:43:44  profilanswer
 

intéressant :)


---------------
J'ai un string dans l'array (Paris Hilton)
n°1258723
Dion
Acceuil
Posté le 04-12-2005 à 22:38:39  profilanswer
 

pkoi ya pas de vraie lib standard  ? :/


---------------
When it comes to business/legal topics, just assume almost everyone commenting has no idea what they’re taking about and have no background in these subjects because that’s how it really is. Harkonnen 8-> Elmoricq 8====>
mood
Publicité
Posté le 04-12-2005 à 22:38:39  profilanswer
 

n°1258731
KangOl
Profil : pointeur
Posté le 04-12-2005 à 22:52:09  profilanswer
 

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 ??

n°1258733
nraynaud
lol
Posté le 04-12-2005 à 22:52:19  profilanswer
 

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 ?

n°1258734
el muchach​o
Comfortably Numb
Posté le 04-12-2005 à 22:53:04  profilanswer
 

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 ?
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 ?


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.


Message édité par el muchacho le 04-12-2005 à 23:07:48
n°1258752
nraynaud
lol
Posté le 04-12-2005 à 23:35:29  profilanswer
 

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.

n°1258753
nraynaud
lol
Posté le 04-12-2005 à 23:36:29  profilanswer
 

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 ...


Message édité par nraynaud le 04-12-2005 à 23:44:10
n°1258754
nraynaud
lol
Posté le 04-12-2005 à 23:38:32  profilanswer
 

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.

Message cité 1 fois
Message édité par nraynaud le 04-12-2005 à 23:43:04
n°1258757
chrisbk
-
Posté le 04-12-2005 à 23:46:11  profilanswer
 

je trouve pas les param out debile [:le kneu]
 
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

n°1258758
el muchach​o
Comfortably Numb
Posté le 04-12-2005 à 23:50:25  profilanswer
 

nraynaud a écrit :


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.


 

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.


Message édité par el muchacho le 04-12-2005 à 23:52:18
n°1258761
nraynaud
lol
Posté le 04-12-2005 à 23:54:13  profilanswer
 

chrisbk a écrit :

je trouve pas les param out debile [:le kneu]


y'en a dans toonaze ? ça m'étonne pas.
 
 
et la valeur de retour, c'est pas mieux pour passer des paramètres ?

n°1258763
chrisbk
-
Posté le 04-12-2005 à 23:56:25  profilanswer
 

nraynaud a écrit :

y'en a dans toonaze ? ça m'étonne pas.


 
non, parce que c'est penible a faire
 
(donc ta gueule quoi [:god])
 

nraynaud a écrit :


et la valeur de retour, c'est pas mieux pour passer des paramètres ?


 
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 :
  1. truc * generatetruc(bla, bla bla, float * factor=NULL);


 
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 [:marc]

Message cité 1 fois
Message édité par chrisbk le 04-12-2005 à 23:56:43
n°1258767
chrisbk
-
Posté le 05-12-2005 à 00:05:31  profilanswer
 

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):
 


p1 <= getOutValue b
p2 <= p1 + c;
c <= p2


 
(la propagation de copie nous eliminera la derniere assignation)
 
 
au passage en IL2 ca se transformera en  
 

mov sym1, a;
mov sym2, [sym1];
mov sym3, c
add sym3, sym2


 
 
 
 
on passe un coup de propagation d'adresse
 
 

Code :
  1. mov sym1, a;
  2. mov sym2, [sym1];
  3. mov sym3, c
  4. add sym3, [sym1]


 
un coup de deadcode
 
 

Code :
  1. mov sym1, a;
  2. mov sym3, c
  3. add sym3, [sym1]


 
et zou
Avec une etude de vie on arrivera a un truc genre
 

Code :
  1. mov eax, a;
  2. mov ebx, c
  3. add ebx, [eax]


 
 
en fait c'est tout con j'aurais pu le faire, et si j'aurais reflechi au pb bin je l'aurais probablement fait [:marc] Faut juste apres se cogner les analyses de flux pour les lectures avant assignation et les sorties sans assignations [:petrus75] merci de m'avoir fait remuer des souvenirs, ca fait plaisir de voir qu'y'en reste deux trois trucs de tout ca


Message édité par chrisbk le 05-12-2005 à 00:08:35
n°1258768
nraynaud
lol
Posté le 05-12-2005 à 00:07:59  profilanswer
 

U teh ehll
 
I don't give a siht to teh suxor out parameter


Message édité par nraynaud le 05-12-2005 à 00:08:16
n°1258769
chrisbk
-
Posté le 05-12-2005 à 00:08:58  profilanswer
 

its because ur too supid to understnad tehir tru power, mroon

n°1258770
chrisbk
-
Posté le 05-12-2005 à 00:10:57  profilanswer
 

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

n°1258775
masklinn
í dag viðrar vel til loftárása
Posté le 05-12-2005 à 00:55:02  profilanswer
 

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 http://membres.lycos.fr/angel2k/petrus/cupetrus.gif
 
(bon par contre tes considérations d'optimisations au cycle près avec ton ASM et tout tu te les fous au cul hein)


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°1259926
blackgodde​ss
vive le troll !
Posté le 06-12-2005 à 12:40:10  profilanswer
 

nraynaud a écrit :


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é.


 
J'ai un peu du mal avec ca aussi


---------------
-( BlackGoddess )-
n°1261640
el muchach​o
Comfortably Numb
Posté le 08-12-2005 à 13:07:18  profilanswer
 

up

n°1263767
++fab
victime du syndrome IH
Posté le 10-12-2005 à 21:43:00  profilanswer
 

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 :)
 
 

n°1263768
chrisbk
-
Posté le 10-12-2005 à 21:45:42  profilanswer
 

++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é.


 
[:pingouino] oscour

n°1263775
el muchach​o
Comfortably Numb
Posté le 10-12-2005 à 22:15:11  profilanswer
 

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 :


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.


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 :


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 :/


Regarde le paragraphe sur les fonctions et les delegates. J'ai explique.

Citation :


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++.


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 :


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 :)


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.

Message cité 1 fois
Message édité par el muchacho le 11-12-2005 à 10:24:40
n°1263777
chrisbk
-
Posté le 10-12-2005 à 22:17:49  profilanswer
 

les templates C++ sont ils seulement comparables aux generics de D

n°1263778
Dion
Acceuil
Posté le 10-12-2005 à 22:19:13  profilanswer
 


 
j'ai rien compris [:pingouino]


---------------
When it comes to business/legal topics, just assume almost everyone commenting has no idea what they’re taking about and have no background in these subjects because that’s how it really is. Harkonnen 8-> Elmoricq 8====>
n°1263779
chrisbk
-
Posté le 10-12-2005 à 22:19:34  profilanswer
 

(cela dit, personne n'est censé aller bidouiller dans la stl)

n°1263781
chrisbk
-
Posté le 10-12-2005 à 22:20:35  profilanswer
 

Dion a écrit :

j'ai rien compris [:pingouino]


 
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
 
 
[:god]
 
 

n°1263782
Dion
Acceuil
Posté le 10-12-2005 à 22:21:36  profilanswer
 

Mais euh ca fait koi export machin toussa ? [:pingouino]


---------------
When it comes to business/legal topics, just assume almost everyone commenting has no idea what they’re taking about and have no background in these subjects because that’s how it really is. Harkonnen 8-> Elmoricq 8====>
n°1263794
el muchach​o
Comfortably Numb
Posté le 10-12-2005 à 22:31:36  profilanswer
 

C'est un peu complique... en gros, ca instancie un template sans vraiment l'instancier.[:god]
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.


Message édité par el muchacho le 10-12-2005 à 22:35:20
n°1263805
el muchach​o
Comfortably Numb
Posté le 10-12-2005 à 22:54:37  profilanswer
 

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++.


Message édité par el muchacho le 10-12-2005 à 22:56:07
n°1263852
Tamahome
⭐⭐⭐⭐⭐
Posté le 11-12-2005 à 10:07:53  profilanswer
 

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...)

n°1263856
el muchach​o
Comfortably Numb
Posté le 11-12-2005 à 10:14:16  profilanswer
 

Ben lis le topic.[:spamafote]
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++).


Message édité par el muchacho le 11-12-2005 à 10:36:29
n°1263968
++fab
victime du syndrome IH
Posté le 11-12-2005 à 14:30:38  profilanswer
 

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 :


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.


 
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 :


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.


 
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++ :|

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3  4  5  6  7  8  9  10
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  [Langage D]C++ + Java + Python = D

 

Sujets relatifs
Upload en JAVA[Java] Architecture pipes-filters
[java] Tracer un rectangle en temps réel[Java] Aide sur projet avec interface graphique ( Pas des fenêtres)
[JAVA] Empecher la saisie dans une jtableimpossible d'éxécuter un programme en java !!!
programmation jeux java sur samsung Z300Envoyer des fichiers sur un FTP depuis un programme Java...
[java] Agrandir le contenu d'une tab en même temps que la tab[Java] Les hint
Plus de sujets relatifs à : [Langage D]C++ + Java + Python = D


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR