Le langage D

Posté par (page perso) . Édité par B16F4RV4RD1N, Bruno Michel, baud123, Xavier Claude, patrick_g, Benoît, lordblackfox, NeoX et Amine "nh2" Brikci-Nigassa. Modéré par NeoX. Licence CC by-sa
Tags : aucun
51
9
juin
2012
Technologie

Le langage D est un langage extrêmement puissant et intuitif à l'utilisation. Nombre d'entre nous sommes au courant de l'existence de ce langage. Mais il reste pourtant mal connu. Par le biais de cette dépêche je vous propose de découvrir ou redécouvrir ce puissant langage.

dlogo

Sommaire

Présentation du langage

Le D se veut adapté au monde moderne du programmeur. Pour cela il tend à combiner puissance de calcul et productivité, la performance d’exécution des langages compilés avec l'intuition des langages de script.

Je préfère vous prévenir une fois l'étape d’apprentissage du langage acquise, il est fortement possible que vous ne souhaitiez plus revenir en arrière.

Le D supporte plusieurs paradigmes, l'expérience a souvent montré que de se restreindre à un paradigme complique dans certains cas la réponse au problème donné.

Ainsi le développeur est mieux armé pour répondre aux différentes problèmatique.

Le langage D a pour devise :

« Si un langage peut récupérer 90 % de la puissance du C++ mais seulement 10 % de sa complexité, cela vaut largement le coup. »
— Walter Bright

Quelques exemples de code

À travers différents exemple de code nous allons vous montrer les bases du langage. L'objectif est d'être bref et de montrer quelques nouveautés facilitant la vie du développeur.

Bonjour paul

Le traditionnel bonjour.

import std.stdio;
void main ( string[] args){
    writef("Bonjour: %s", args[1] );
}

L'instruction import indique ici que l'on souhaite utiliser des fonctionnalités définies dans le module stdio d'où provient la fonction writef.

Le programme commence a exécuter les instructions à partir de la fonction principale main. Cette fonction récupère ici les paramètres donnés via la ligne de commande.

La fonction writef va écrire sur la sortie standard le mot Bonjour suivi du premier mot donné via la ligne de commande.

$ ldc2 hello.d
$ ./hello paul
Bonjour paul

Une petite addition

À travers une opération simple qui est l'addition, nous allons découvrir comment écrire et utiliser les fonctions et les fonctions modèles (template).

import std.stdio;

@safe pure nothrow
size_t ajoutez( immutable size_t a, immutable size_t b = 0){
    return a + b;
}

void main ( string[] args ){
    size_t c = ajoutez( 2 , 3 );
    size_t d = ajoutez( 2 );
    size_t e = ajoutez( cast(size_t)2.3 , cast(size_t)3.3 );
    writef( " 2 + 3 = %d  | 2 + 0 = %d | 2.3 + 3.3 = %d", c, d, e);
}

$ ldc2 addition.d
$ ./addition
2 + 3 = 5 | 2 + 0 = 2 | 2.3 + 3.3 = 5

La fonction ajoutez prend deux paramètres de type entier positif et retourne une valeur de type entier positif. La fonction ajoutez tronque les valeurs décimales dues aux types utilisés. Si le second paramètre est omis il prendra par défaut la valeur 0.

En Bref :

  • @safe indique que la fonction est sûre, devant suivre les règles décrites ici, il s'agit d'éviter des comportements indéfinis pouvant poser des problèmes de sécurité comme les cast de variable vers un pointeur, l'écriture de langage d'assemblage inline, le catch d'exception ne dérivant pas de la classe Exception
  • pure indique que :
    • les mêmes paramètres donneront toujours le même résultat (si a vaut et b vaut 2, a+b sera toujours égale à 4) 2+2 est donc calculé une fois ; les autres fois il connaîtra le résultat sans calculer.
    • Pas d'effet de bord en n'effectuant pas de modification d'état des variables comme a+=2
  • nothrow indique que la fonction ne lève pas d'exception
  • immutable les variables ne peuvent pas changer d'état.
import std.stdio;

T ajoutez(T,U)( T a, U b ){
    return a + b;
}

void main ( ){
    double c = ajoutez( 2.4 , 3 );
    auto   d =  ajoutez( 2 , 3 );
    writefln( "2.4 + 3 = %f", c);
    writefln( "2 + 3 = %d", d);
}

$ ldc2 addition2.d
./addition2
2.4 + 3 = 5.4
2 + 3 = 5

Afin de pouvoir adapter dynamiquement la fonction ajoutez aux types donnés en paramètre et ainsi éviter d'écrire plusieurs fonctions combinant toutes les possibilités, on utilise les fonctions template.

Le D est capable de déterminer automatiquement le type des variables retournées, on peut ainsi utiliser le mot clé auto en lieu et place du type.

Les conditions par l'exemple

    string a = "bonjour";
    if( a == "coucou")
        writeln( "ok" );
    else if( a == "bonjour")
        writefln( "%s", a );
    else
        writeln("raté");

Si la variable a est égale à coucou on écrit sur la sortie standard ok.
Sinon si a est égale à bonjour on écrit sur la sortie standard bonjour.
Sinon pour tous les autres cas on écrit sur la sortie standard raté.

Note : Les blocs ne contenant qu'une seule instruction sont dispensés des accolades {} . Ceci est vrai pour les conditions et les boucles.

    string a = "bonjour";
    switch(a){
        case "coucou": writeln( "ok" ); break;
        case "bonjour": writefln( "%s", a ); break;
        default: writeln("raté");
    }

Ce bout de code fait exactement pareil que la suite if, else if, else précédente.

Les tableaux

Les tableaux Dynamiques

size_t[] tab     = new size_t[](5); // tableau dynamique de taille 5
size_t[] tableau = [ 0, 1, 2]; // tableau dynamique d'entier positif
tableau.length; // retourne la taille de 3
tableau[0]; // Accède au premier élément du tableau
tableau[3]; // erreur le tableau contient 3 éléments en partant de 0
tableau.length = tableau.length + 1; // augmente la taille du tableau
tableau[3] = 3; //  Assigne la valeur de 3 en 4ème position

Les tableaux statiques

size_t[3] tableau = [ 0, 1, 2]; // Tableau statique d'entier positif
tableau.length; // Retourne la taille de 3
tableau[0]; // Accède au premier élément du tableau
tableau[3]; // Erreur le tableau contient 3 éléments en partant de 0
tableau.length = tableau.length + 1; // Erreur on peu pas augmenter
                                     // la taille d'un tableau statique

Les tableaux associatifs

 size_t[string] catalogue; // la clé est une chaine de caractère,
                           // la valeur un entier positif
catalogue["fedora"] = 17;  // ajoute la clé fedora asssocié à la valeur 17
"fedora" in catalogue;     // retourne vrai (true)
catalogue["fedora"];       // retourne la valeur 17

Les tableaux de types différents

import std.stdio;
import std.variant;

void main( string[] args ){
    Variant[] v = new Variant[](3);
    v[0] = 1;
    v[1] = 1.2;
    v[2] = "test";
    writeln( v );
}

$ ldc2 test_variant.d
$ ./test_variant
[1, 1.2, test]

Les tableaux de caractères

  • le guillemet simple ' désigne un caractère char lettreA = 'a';
  • le guillemet double " désigne une chaine de caractère string mot = "salut";
  • le backticks (accent grave)` désigne une chaine de caractère gardant le formatage (wysiwyg)

string mots = `J'aime le D.
C'est super cool comme langage`.

Répéter le code : Les boucles

La boucle Pour chaque (foreach)

import std.stdio;

void main ( ){
    foreach( size_t count; 0 .. 3)
        write( count, " " ); // écrit sur la même ligne
    writeln(); // saut de ligne

    size_t result = 0;
    foreach( size_t count; 0 .. 3){
        result += 2;
        write( result, " " ); // écrit sur la même ligne
    }
    writeln(); // saut de ligne

    foreach( size_t count, string prénom; [ "jean", "Marie", "Paul" ] )
        writef( "%d ↪ %s | ", count, prénom ); // écrit sur la même ligne
    writeln(); // saut de ligne

    string[string] personnes = [ "jean": "Debian", "Marie": "CentOs", "Paul": "Fedora" ]; // tableau associatif
    foreach( string prénom, string disribution; personnes )
        writefln( "%s utilise GNU Linux %s", prénom, disribution );
    foreach( ref string distribution; personnes )
        distribution = "Fedora";
    writeln( personnes );
}

$ ldc2 test_foreach.d
$ ./test_foreach
0 1 2 
2 4 6 
0 ↪ jean | 1 ↪ Marie | 2 ↪ Paul | 
jean utilise GNU Linux Debian
Paul utilise GNU Linux Fedora
Marie utilise GNU Linux CentOs
["jean":"Fedora", "Paul":"Fedora", "Marie":"Fedora"]

La boucle foreach s'utilise de façon intuitive et peut avoir au besoin un compteur comptant le nombre d'itération. Afin de modifier sur place le contenu du tableau il suffit de préciser que la valeur est une référence (ref) à l'élément du tableau.

Vous remarquerez qu'il est possible d'utiliser des caractères unicode pour le nom des variables. En effet, le D gère nativement l'unicode, par exemple les statisticiens peuvent utiliser les lettres lambda λ, mu μ, rho ρ et sigma σ.

La boucle Pour (for)

import std.stdio;

void main ( ){
    size_t result = 0;
    for( size_t count = 0 ; count <= 10; count++ ){
        result += 2;
        writeln( result );
    }
}

La boucle tant que (while)

bool isRunning = true;
size_t i = 0;
while( isRunning ){
    if( i >= 10 )
        isRunning = false;
    else
        i++;
}

Les structures de données

Il y a deux structures de données possibles : les structures et les classes. Les classes sont utilisées lorsque l'on a recourt à l'héritage ; dans tous les autres cas on utilise les structures.

Note :

  • Surcharge :
    • Les méthodes peuvent avoir le même nom mais prenant des paramètres différents
    • Une méthode peut avoir le même nom et prenant les mêmes paramètres que ceux d'une classe parente. On parle de même signature : nom de la fonction + paramètres.

Les structures

Les structures en D ont eu quelques améliorations permettant une utilisation simple et efficace.

import std.string : format, toUpper; // import sélectif
import std.stdio;

struct Personne{
    private:
    string _nom;
    string _prénom;
    size_t _âge;

    public:
    this(string nom, string prénom, size_t âge = 18){ // constructeur
        _nom    = nom;
        _prénom = prénom;
        _âge    = âge;
    }

    string toString(){
        return "Je m'appelle %s %s et j'ai %d ans".format( _nom.toUpper(), _prénom, _âge);
    }

    @property
    string nom(){
       return _nom;
    }
    @property
    string prénom(){
       return _prénom;
    }
    @property
    size_t âge(){
       return _âge;
    }
}

void main(){
    Personne p1 = Personne( "dupont", "paul", 34 );
    Personne p2 = Personne( "durant", "louis" );
    writeln( p1 );
    writeln( p2 );
    if( p1.nom == "dupont" ) writeln( "Bonjour dupont" );
    else writefln( "non!, Je m'appel %s", p1.nom );
}

$ ldc2 personne.d
$ ./personne.d
Je m'appelle DUPONT paul et j'ai 34 ans
Je m'appelle DURANT louis et j'ai 18 ans
Bonjour dupont

En bref :

  • import sélectif
  • les structures peuvent avoir un constructeur (pas obligatoire)
  • les variables peuvent être publiques ou privées (protected, aucun intérêt en absence d'héritage)
  • @property permet de ne pas utiliser () lors d'appel de méthode
  • toString permet de représenter l'instance par une chaîne de caractère

Les classes

Les classes s'utilisent comme les structures et permettent l'implémentation de l'héritage d'une autre classe ou d'une interface. Le langage D ne supporte pas l'héritage multiple.
En reprennant l'example de la structure précédente :

import std.string : format, toUpper; // import sélectif
import std.stdio;

class Personne{
    protected:
    string _nom;
    string _prénom;
    size_t _âge;

    public:
    this(string nom, string prénom, size_t âge = 18){ // constructeur
        _nom    = nom;
        _prénom = prénom;
        _âge    = âge;
    }

    override string toString(){
        return "Je m'appelle %s %s et j'ai %d ans".format( _nom.toUpper(), _prénom, _âge);
    }

    @property
    string nom(){
       return _nom;
    }
    @property
    string prénom(){
       return _prénom;
    }
    @property
    size_t âge(){
       return _âge;
    }
}

class Mage : Personne{
    protected:
    size_t _level;
    size_t _mana;

    public:
    this(string nom, string prénom, size_t âge = 18, size_t level = 1){
        super( nom, prénom, âge);
        _level = level;
        _mana   = _level * 10;
    }

    @property
    size_t bouleDeFeu(){ // puissance de la boule de feu
        size_t dégât = 0;
        if( _mana > 5 ){
            _mana -= 5;
            dégât = _level *  2;
        }
        return dégât;
    }

    @property
    size_t level(){
        return _level;
    }

    @property
    size_t mana(){
        return _mana;
    }

    override string toString(){
        return "Je suis %s %s le mage de feu".format( _nom.toUpper(), _prénom);
    }
}

void main(){
    Personne p1 = new Personne( "dupont", "paul", 34 );
    Mage m1 = new Mage( "durant", "louis", 18, 15 );
    writeln( p1 );
    writeln( m1 );
    if( cast(Mage) m1 ) writefln( "Bonjour je suis un mage de niveau %d", m1.level);
}

$ ldc2 mage.d
$ ./mage 
Je m'appelle DUPONT paul et j'ai 34 ans
Je suis DURANT louis le mage de feu
Bonjour je suis un mage de niveau 15

En bref :

  • On utilise les classes si on utilise l'héritage
  • Création d'une instance avec le mot clé new (ce n'est pas vrai pour les structures)
  • Spécification de surcharge de méthode avec override

Pour aller plus loin

Un aperçu sur la parallèlisation

Un petit exemple d'itération parallèle, plus d'exemple sur le site officiel.

import std.stdio;
import std.parallelism;

void main(){
    TaskPool taskPool = new TaskPool(9);
    string[] prénoms = [ "Paul", "Jean", "Pierre", "Julie", "Robert", "Jonathan", "Julien", "Sabrina", "Laetitia" ];
    foreach( prénom; taskPool.parallel(prénoms) )
        writeln(prénom);
    taskPool.finish(); 
}

$ ldc2 test_parallel.d
$ ./test_parallel 
Paul
Jean
Pierre
Julie
Julien
Jonathan
Robert
Sabrina
Laetitia

Une delegate pour la route (closure)

À la mode fonctionnelle

import std.stdio;

void main(){
  immutable size_t n = 2;
  immutable size_t x = 1;
  pure size_t inc( size_t k ){ return n + k; }
  pure size_t f( in size_t delegate(size_t) pure dg1, in size_t delegate(size_t) pure dg2) {
    return dg1( x ) + dg2( x );
  }
  immutable size_t delegate(size_t k) pure dg = &inc;
  writeln( f( dg , dg ) );
}

$ ldc2 fonctionnelle.d
$ ./fonctionnelle
6

En bref :

  • La fonction inc (pour incrémente)
    • capture la variable n qui est dans le contexte local
    • retourne la somme de n local + k passé en paramètre
  • la fonction f
    • prend en paramètre deux fonctions ayant la même signature que dg
    • additionne le résultats des deux fonctions ( 2 + 1 ) + ( 2 + 1 )
    • retourne le résultat
  • La fonction dg positionne la fonction inc comme delegate
    • prenant en paramètre un entier positif
    • retournant comme résultat un entier positif

De façon non-fonctionnelle

import std.stdio;

void main(){
    size_t n = 2;
    size_t x = 1;
    void f( size_t a){ writeln( a ); }
    int inc(size_t k) { n = n + k; return n; } //incremente n d'un pas k
    f( inc(x) + inc(x) ); // f( 2+1 + 3+1 ) => 7
}

En bref :

  • À la différence de la façon fonctionnelle
    • n subit un changement d'état dans la fonction inc
    • la fonction inc
      • capture la première fois n valant 2
      • capture la seconde fois n valant 3
      • car n a subi un changement d'état au premier passage dans inc

Distributions linux conseillées pour le D

  • Fedora fournit dans les dépôts officiels :

    • ldc (compilateur libre basé sur LLVM)
    • phobos 2.059 (bibliothèque standard)
    • tango2
    • gtkD (un wrapper pour gtk )
    • derelict2 (pour les appli 3D avec des wrapper comme pour SDL… )
    • dustmite (outil pour réduire un programme en un code minimal produisant le segfault)
  • Debian via le dépôt non-officiel d-apt

    • dmd ( compilateur avec restriction de droit )
    • gtkd
    • tango
    • plot2kill
    • dcollections
    • orange ( serialisation )
    • scid
    • spiritd
    • dstats
    • msgpack
    • derelict
    • gl3n
    • dsqlite
    • vibe
  • Archlinux fournit dans son dépôt officiel :

    • ldc
    • phobos
    • et d'autres paquets (derelict, gtkd…) dans AUR, du côté des contributions utilisateurs.

Mythes et légendes

De nombreuses idées persistent, nous allons ici en répertorier quelques unes.
Dans la catégorie, le langage D est:

  • Un langage propriétaire :
    Faux : les compilateurs ldc et gdc fournissent une implémentation libre de ce langage

  • Peu utilisé : Ceci est également de moins en moins vrai. Ce langage devient populaire outre-atlantique. La forge github répertorie le D en 25ème position en terme de quantité de projet utilisant ce langage au sein de leur infrastructure.

  • En bêta : Non : le langage D est bel et bien stable et des améliorations périodiques sont mises à disposition.

  • Possède deux bibliothèques standard : Non, depuis plusieurs années la bibliothèque standard est Phobos, le pendant de la STL + Boost en C++ .

  • # Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

    Posté par . Évalué à 4.

    Tout d'abord, excellente dépêche qui aborde beaucoup de points. Du coup, ça me donne à mon tour l'envie de répondre sur ces points. ;-)

    @safe pure nothrow
    
    

    Je trouve que cette ligne est une sorte de blague. Enfin… le @safe se défend, mais le pure et le nothrow, pourquoi ? C'est quelque chose qui se détecte facilement. Ça donne plutôt l'impression d'ornements superflus dans le code. Même remarque pour l'immutable.
    D'ailleurs je ne comprends même pas pourquoi ce n'est pas le mode par défaut et mutable l'exception.

    Peut-on avoir une explication sur l'utilisation du type size_t au lieu d'un équivalent de l'unsigned int ? Est-ce un remplacement courant ?

    • [^] # Re: Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

      Posté par . Évalué à 3.

      Détecter la pureté d'une fonction n'est pas évident. Particulièrement si celle ci fait des appels systèmes, touche au tas, ou fait appel à d'autres fonctions qui ne sont pas pures. C'est un problème indécidable. Maintenant, effectivement, dans les cas où ça ne permet pas au compilo de faire des grosses optimisation, c'est probablement à ranger dans les ornements superflus.

      Please do not feed the trolls

    • [^] # Re: Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

      Posté par . Évalué à 2.

      immutable permet une plus grande sécurité que const, c'est une des directions majeurs de D2 par rapport à D1.

      Sinon pour size_t, non c'est pas vraiment courant dans les sources que tu trouveras, j'avoue que ça fait pas très idiomatique.
      C'est juste la façon de coder de l'auteur. :)

      • [^] # Re: Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

        Posté par . Évalué à 1.

        immutable permet une plus grande sécurité que const, c'est une des directions majeurs de D2 par rapport à D1.

        Peux-tu développer ?

        • [^] # Re: Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

          Posté par . Évalué à 4.

          Quand une data est marquée immutable, elle ne pourra jamais changer, elle sera de même valeur durant toute l’exécution du programme, comme dans un langage fonctionnel.
          Au niveau de la concurrence de D2, immutable permet d'être thread-safe.
          Donc vu que le compilo sait que la data est immutable, il peut optimiser en fonction.

          Tandis que const donne juste la garantie qu'une référence vers la data marquée const ne changera pas celle ci(la référence), par contre une autre référence vers le même objet est en droit de le modifier.(alors qu'avec immutable non)

          En gros immutable est à utiliser quand la data doit rester la même du début à la fin de l'éxécution et const est plus pour garantir que la data ne sera pas modifier avec l'identificateur marqué const.(en paramètre d'une fonction par ex.)

          void main()
          {
              int[] a = [1, 2, 3];
              immutable(int)[] b = a; //Error: cannot implicitly convert expression (a) of type int[] to immutable(int)[]
              b[0] = 0; // ne compilera oh grand Dieu jamais
          }
          
          
          void main()
          {
              int[] a = [1, 2, 3];
              const(int)[] b = a; // compile
              a[0] = 0;//compile
              b[0] = 0;//compile pas
          }
          
          

          Ceci t'expliquera mieux que moi ;)

          • [^] # Re: Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

            Posté par (page perso) . Évalué à 2.

            Si je comprend bien, le immutable du D correspond au const du C++.

            « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

            • [^] # Re: Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

              Posté par . Évalué à 4.

              Non absolument pas, tu te doutes bien que si les programmeurs D sont contents d'immutable c'est parce qu'ils aiment pas trop le const de C++.

              Le const de C++ n'est pas transitive, tandis que le const et l'immutable de D le sont.
              Le const de C++ n'offre quasiment aucune garantie au niveau de la thread-safety.

              Le const de C++ se rapproche plus du const de D(avec notamment la notion de transitivité comme grosse différence), certainement pas d'immutable. :)

              • [^] # Re: Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

                Posté par . Évalué à 1.

                Sauf que const est aussi transitif en C++ pour les types composites.

                Avec gcc, le code suivant renvoi une erreur:

                struct A
                {
                  A() : a(0) {}
                  int a;
                };
                
                int main(int argc, char** argv)
                {
                  const A a;
                  a.a = 1;
                }
                
                

                Par contre avec const int **p, en D tout est constant p, *p, **p, et c'est pas le cas en C++, et tant mieux. C'est quand même vachement pratique de pouvoir maintenir des listes de pointeurs vers des tableaux de constantes. Et si on veut que p, *p, **p soient constant, on écrit ça:

                const int* const* const p;
                
                

                C'est un peu lourd, mais ça a le mérite d'être claire.

                Après pour ce qui est d'être thread-safe, j'ai l'impression que la seule raison pour qu'immutable soit plus sûr est l'impossibilité de faire un const_cast (ou plutot immutable_cast). Mais si on utilise pas const_cast, je vois pas en quoi le const de C++ est moins thread-safe que le immutable de D.

                • [^] # Re: Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

                  Posté par . Évalué à 6.

                  Mais si on utilise pas const_cast, je vois pas en quoi le const de C++ est moins thread-safe que le immutable de D.

                  Parce qu'une référence const peut être obtenu à partir d'une référence non-const en C++. La référence non-const peut être modifiée, modifiant ainsi la référence const depuis un autre endroit. En revanche, une référence immutable ne peut pas être obtenue depuis une référence non-immutable.

                  int x = 0;
                  const int &y = x;
                  x = 42; // y est modifié (à replacer dans un contexte multi-thread)
                  
                  
      • [^] # Re: Le langage D est-il choisi lorsqu'on ne sait pas avec quoi coder ?

        Posté par . Évalué à 8.

        Sinon pour size_t, non c'est pas vraiment courant dans les sources que tu trouveras, j'avoue que ça fait pas très idiomatique.
        C'est juste la façon de coder de l'auteur. :)

        Prétendre que tout est un index / une taille d'objet ? Hm curieuse façon ; il faudrait ptet qu'il se soigne.

  • # Il y a encore du boulot

    Posté par (page perso) . Évalué à 0.

    $ more /etc/debian_version
    6.0.4
    (bref du pas vieux)
    $ apt-cache search ldc2
    (rien)
    $ apt-cache search ldc
    ldc - LLVM D Compiler
    $ sudo apt-get install ldc
    (bla bla)
    $ ldc --version
    LLVM D Compiler rev.
    based on DMD v1.056 and llvm 2.6 (Fri Feb 26 11:01:51 2010)
    $ more a.d
    import std.stdio;
    void main ( string[] args){
    writef("Bonjour: %s", args[1] );
    }
    $ ldc a.d
    a.d(1): Error: module stdio cannot read file 'std/stdio.d'

    Ca donne envie de découvrir… Ou pas.
    Surtout qu'en lisant le "hello world" je n'ai absolument aucune idée de la valeur retour du programme, génant.
    En pratique, j'étais curieux de savoir comment le programme réagissait si on lui donne aucun paramètre. Bref, savoir si le programme est viable et ne crashe pas suivant le désir de la ligne de commande. Mais je ne peux pas, vu que ça ne compile pas.

    • [^] # Je cherche à comprendre

      Posté par (page perso) . Évalué à -9.

      http://dlang.org/download.html

      DMD - Digital Mars D Programming Language version 1 (please note: D1 will be discontinued effective December 31, 2012)

      Pardon? Je ne comprend pas : ce qui a été fait en D version 1 ne sera plus supporté?

      Bon, prenons un compilo "version 2" sous Windows (devinette : pas de ldc sous Windows, c'est du "dmd")

      $ more a.d
      import std.stdio;
      void main ( string[] args){
      writef("Bonjour: %s", args[1] );
      }
      $dmd a.d
      (vide)
      $a.exe Jerome
      Bonjour: Jerome
      $a.exe Jérôme
      Bonjour: J├®r├┤me
      $a.exe

      core.exception.RangeError@a(3): Range violation
      ----------------
      4149D4
      41485F
      40202D
      4070AA
      406CCB
      41BC89
      ----------------
      
      

      Résumé :
      - Install Windows pourrie : pas d'IDE, on balance la ligne de commande et démerde-toi. Comparé à Visual Studio, c'est à pleurer
      - D n'a pas l'air de connaitre autre chose que du ASCII 7-bit. On est en 2012!
      - Quelqu'un qui fait une démo du programme n'est pas capable de proposer un exemple qui ne crashe pas. Hum.

      C'est vraiment si intéressant? avec C/C++, j'ai un IDE (Visual Studio Express par exemple), et une gestion correcte des accents en ligne de commande en programme de base! Un test vite fait certes, mais ça ne laisse pas augurer d'une bonne qualité pour la suite si juste ça merde autant…


      J'ai y mis du mien (je pense) pourtant, il me semble… Mais ça n'attire pas.

      • [^] # Re: Je cherche à comprendre

        Posté par (page perso) . Évalué à 10.

        pour le range error c'est normal je n'est mis aucune vérification ce n'était pas l'objectif.
        Pour ce qui est des caractère unicode le D le gère nativement dans le cas de windows c'est la console windows qui ne gère pas les caractères unicode. Comme tu l'a dit en 2012 un OS qui gère pas sur la console l'unicode …

        • [^] # Re: Je cherche à comprendre

          Posté par (page perso) . Évalué à 2. Dernière modification le 09/06/12 à 18:34.

          import std.stdio;
          import std.array;
          void main ( string[] args){
              if( args.length == 2 )
                  writefln("Bonjour: %s", args[1] );
              else if ( args.length > 2 )
                  writefln("Bonjour: %s", args[1..$].join(", ") );
              else
                  writefln("Bonjour" );
          }
          
          
          $ ./t
          Bonjour
          $ ./t jean paul eric
          Bonjour: jean, paul, eric
          
          
        • [^] # Re: Je cherche à comprendre

          Posté par (page perso) . Évalué à -7.

          Bonjour, vous utiliser une très veille version du langage.

          Le langage n'est pas déjà très connu qu'il a déjà changé? Ouch… On parle d'un "Hello World" la, pas d'un truc compliqué, et ça, ça a déjà changé… Alors que j'ai pris une Distro (pas des plus inconnues) sortie il y a un an.

          pour le range error c'est normal je n'est mis aucune vérification ce n'était pas l'objectif.

          Ah? Fournir un exemple qui est pourri est acceptable "car pas l'objectif"? Hum, je crois que ça ferai un 0 pointé à l'école ça. Le mieux est alors ne pas utiliser args[1] plutôt que de faire un programme qui crashe en 1 seconde.

          Pour ce qui est des caractère unicode le D le gère nativement dans le cas de windows c'est la console windows qui ne gère pas les caractères unicode. Comme tu l'a dit en 2012 un OS qui gère pas sur la console l'unicode …

          Reporter la faute sur l'OS est à mourir de rire. Je fais la même chose, en C, C++, C#, Python, autre, et ça marche très bien, merci, le programme sait très bien me renvoyer du texte dans la même locale que la ligne de commande. Non, ici, c'est le compilo / langage qui a un gros bug : il ne sait pas répondre dans la même locale que la commande appelante. Énorme, mais ça ne dérange pas.


          Bon, ben je crois que ça va suffire : ça refroidit pas mal. Autant dans la maturité du langage, de son "IDE" (la ligne de commande) mis en publicité sur le site (j'ai pris l'installeur Windows le plus visible), que les principes d'une personne qui aime ce langage "ce n'est pas mon poulain qui a un problème, c'est ton OS même si tous les autres savent faire correctement" ou "je fais des programmes qui crashent et ça ne me dérange pas", hum. Je vais rester à mon C++ (mettre ici un autre langage : Python, Java, C#…) en attendant qu'on me fasse une meilleur publicité un jour. La, ça ne donne vraiment pas envie d’approfondir.

      • [^] # Re: Je cherche à comprendre

        Posté par . Évalué à 5.

        Je n'ai pas ce problème d'accent ni sous osx, ni sous linux

        Pour l'exception, ça ne me choque pas, tu tentes d'acceder à un tableau vide, sans gérer les exceptions, ces un comportement normal selon moi.

        Pour l'ide, sur le site de digital mars il propose un plugin pour visual, pour eclispe, et ils proposent d'autres ide. Je ne les ai pas essayés, je ne sais pas ce qu'ils valent

        Néanmoins c'est un problème plutôt récurent de tout les langages qui ne sont pas "mainstream". Même pour ruby je ne trouve pas d'ide libre où même gratuit et de bonne facture. (en payant et proprio, j'aime beaucoup rubymine par contre)

        • [^] # Re: Je cherche à comprendre

          Posté par (page perso) . Évalué à -3. Dernière modification le 09/06/12 à 18:54.

          sans gérer les exceptions, ces un comportement normal selon moi.

          Le comportement du langage ne me choque pas. Ce qui me choque ici, c'est que quelqu'un ose écrire ce genre de programme comme exemple alors qu'il crashe. Il me semble un minimum pour présenter un langage, de proposer des exemples "valides" (un " writef("Bonjour le monde" ) " ne m'aurai pas choqué, la on a piqué ma curiosité à ne pas faire de test, si la personne ne met pas de test en "améliorant" le classique "Hello world", j'imagine "bêtement" que c'est parce qu'il a délégué la chose au langage et qu'il voulait le montrer, mais non). Comment prendre au sérieux le reste si la base crashe faute d'exemple correct? Ca ne rassure pas du tout.

        • [^] # Re: Je cherche à comprendre

          Posté par (page perso) . Évalué à 3.

          Je ne pense pas qu'il soit dans une démarche constructive étant donné que sous C++ le code aurait le même comportement. Mais plutot une volonté de nuire.

          Le soucis sous pour l'encodage des caractères c'est qu'il n'est pas possible de connaitre l'encodage de ta console aussi simplement. Tu peux créer des moyens plus ou moins automatique pour connaitre l'encodage de la console et ainsi obtenir des caractères lisibles sur ta console. le module std.encoding est utilisé en ce sens.

          Pas la peine de mettre de la méchanceté ou toute autre démarche ayant pour simple but de nuire. De la a dire que c'est pas normale que le programme plante car on dépasse volontairement le tableau et que c'est pas normal. c'est un peu fort de café surtout que le C++ segfaulterait tout au temps. Idem pour l'encodage il faut préciser la locale utiliser par la console en C++.

          Je ne pense pas qu'il soit intéressant ou constructif de s'énerver. Discutons débattons paisiblement bien que le sujet des langage tends a attirer les trolls …

          • [^] # Re: Je cherche à comprendre

            Posté par (page perso) . Évalué à -4.

            Je ne pense pas qu'il soit dans une démarche constructive étant donné que sous C++ le code aurait le même comportement.

            Ici, je ne critique pas le langage, ne t'en déplaise. Ici, je critique la personne qui écrit ce code qui plante.

            Nuire? J'en ai rien à foutre de D, aucune volonté de nuire. Tu as piqué ma curiosité à présenter un code démonstratif qui ne fait pas de test sur la taille avant d'utiliser un index. J'ai donc testé. J'en ai chié pour tester, même sous Linux : même pas capable d'avoir un truc à jour sur le repo officiel d'une des distros les plus connues (testé sur OpenSUSE aussi, pas trouvé), ça ne laisse rien présager de bien sur la maintenabilité du langage (il va mourir quand?). Certes, ensuite on a les paquets, et c'est bien. Ca reste un problème quand même de mon point de vue : impossible de dire aux gens de compiler à partir des sources, il n'ont pas le compilo sur leur distro.

            Le soucis sous pour l'encodage des caractères c'est qu'il n'est pas possible de connaitre l'encodage de ta console aussi simplement.

            Comment font les autres, bon dieu… Ah non, ne surtout pas remettre en cause le compilo (bug pour Windows seulement à priori). Désolé, je lui file une chaîne de caractère en entré, c'est le minimum de me rendre la même chaîne de caractère dans la même locale. Ca ne te choque pas qu'il me renvoie un truc pourri qui n'a rien à voir avec l'input alors que j'ai rien configuré comme locale, que je garde la même locale en sortie qu'en entrée? Non, il y a un bug. Ne pas le reconnaître fait peur.

            Je ne pense pas qu'il soit intéressant ou constructif de s'énerver.

            Il est tout autant reconnaissant de reconnaître qu'on s'est planté en écrivant du code et de reconnaître qu'il y a des bugs plutôt que de se cacher derrière des excuses des plus énormes. Ici, je n'attaque pas le langage (les développeurs ne sont pas la, pas leur faute), mais celui qui cherche des excuses des plus foireuses. Mais je te rassure : je vais m'arrêter la, tu as piqué ma curiosité, puis déçu (c'est le codeur qui fait du code mauvais, pas le langage qui a une super-fonctionnalité par rapport aux autres), l'accueil est "c'est toi et ton OS qui avaient tord", je vais me dépêcher de partir et ne plus t’embêter. Ca plait aux autres, ça ne les dérange pas, OK, amusez-vous!

          • [^] # Re: Je cherche à comprendre

            Posté par (page perso) . Évalué à 1.

            Je ne pense pas qu'il soit dans une démarche constructive

            C'est juste le pénible de service sur linuxfr, tu peux sans regret faire comme tout le monde, le moinsser et lire les réponses intelligentes :-)

            http://devnewton.bci.im

            • [^] # Re: Je cherche à comprendre

              Posté par . Évalué à 2.

              Si ses méthodes d'argumentation font controverse, le fond de ses remarques est souvent juste et il sait reconnaître quand il a tort.
              En l'occurrence, ici, il y a un problème de gestion d'encodage, et ce problème n'est pas dans la console utilisée. Également, l'intérêt d'un programme d'exemple est de montrer les bonnes pratiques, par exemple en vérifiant les entrées pour que le programme ne plante pas.

      • [^] # Re: Je cherche à comprendre

        Posté par . Évalué à -8.

        Install Windows pourrie : pas d'IDE, on balance la ligne de commande et démerde-toi. Comparé à Visual Studio, c'est à pleurer

        C'est toi qui est à pleurer. En outre cmd.exe c'est vraiment du caca par rapport à Gnome, windows c'est vraiment de la merde.

        Quelqu'un qui fait une démo du programme n'est pas capable de proposer un exemple qui ne crashe pas. Hum.

        wtf

      • [^] # Re: Je cherche à comprendre

        Posté par . Évalué à 6.

        • D n'a pas l'air de connaitre autre chose que du ASCII 7-bit. On est en 2012!

        J'ai bien l'impression que D a fait la même erreur que C++ : le type string n'est qu'un char[] amélioré, c'est à dire qu'il stocke des octets, pas des caractères, string ne gère donc pas Unicode et laisse le développeur gérer l'encodage lui-même. Comme vous dites, faire encore cette erreur en 2012 est idiot.

        • [^] # Re: Je cherche à comprendre

          Posté par (page perso) . Évalué à 2.

          Non justement, de base

          • char => caractère unicode 8
          • string => tableau de caractère unicode 8 + fonction manipulation de chaine + immutable
          • wchar => utf 16
          • dchar => utf32

          si le développeur veut utiliser autre chose que de l'unicode dans ce cas il le précise par le biais de la locale ou réencode juste la chaine de caractère voulu

          • [^] # Re: Je cherche à comprendre

            Posté par . Évalué à 3.

            char => caractère unicode 8

            "unicode 8" ? Qu'est ce que c'est ? UTF-8 ? Sur Windows, argv n'est pas en UTF-8, et si D ne convertit pas lui-même les arguments avant d'entrer dans main, alors c'est bien un bug de D.

            • [^] # Re: Je cherche à comprendre

              Posté par . Évalué à 2.

              Je ne pense pas que ça soit au langage de faire des trucs magiques sans l'accord du dev.

              Sur Windows, argv n'est pas en UTF-8

              Windows ou le term, est ce le même comportement avec powershell, cygwin, ou je ne sais quel autre terminal ?

              • [^] # Re: Je cherche à comprendre

                Posté par (page perso) . Évalué à 5.

                Je ne pense pas que ça soit au langage de faire des trucs magiques sans l'accord du dev.

                Perso, je suis curieux de savoir justement quels trucs magiques le compilo me fait sous Windows : je lui balance une chaîne 8-bit, il me ressort une autre chaine 8-bit, différente. La, c'est magique, clairement. Mais je ne connais pas cette magie, malheureusement. C'est plutôt gênant (mais à priori seulement un bug du compilo sous Windows, pas de conception du langage, vu que ça marche ailleurs)

                • [^] # Re: Je cherche à comprendre

                  Posté par . Évalué à 1.

                  Perso je pense plus à un bug du term, comme ça m'arrivait si souvent sous linux fut une époque

                  • [^] # Re: Je cherche à comprendre

                    Posté par (page perso) . Évalué à 4.

                    Le term va très bien, je vis avec cette horreur (oui, il est horrible ce term) avec les autres langages et 36 compilos, et j'en ai eu des problèmes avec lui (car par défaut il n'est pas UTF-8 mais "à l'ancienne" façon Linux avant UTF-8, et du coup il a du mal si je m'amuse avec des caractères qui ne sont pas sur la locale de l'OS utilisé (la locale change suivant la région) alors que j'ai des caractère d'un autre endroit (fichier, réseau etc, la j'en chie bien car du coup je n'ai pas la même locale en input et output, et je dois configurer la local de sortie du coup).

                    Bref, non, faudrait arrêter d'accuser le term : ici, je teste un input et un output du même term avec donc la même locale, la même configuration. Comme le dit BFG, c'est sans doute un bug de writefln qui ne gère pas de la même manière que le "readfln" (je sais pas comment l'appeler pour l'input) sur un même term, ce qui est un bug (désolé, mais ça me fait bizarre que deux fonctions n'utilisent pas la même façon de se configurer pour un même term). Ce qui me fait peur, c'est que l'OS utilisé n'est pas un OS ayant une part de marché ridicule. Avoir ce genre de bug est rédhibitoire pour moi. Alors, la chance sous Linux est sans doute que writefln écrit du UTF-8 quoi qu'il arrive et que par hasard, et seulement par hasard, vous êtes en UTF-8, mais si vous n'y êtes pas en UTF-8?

                    C'est un bug, ça arrive, pas de soucis. Ce qui m'a fait réagir ici est qu'on ne se pose pas la question du tout si ça peut venir du compilo, on fonce direct sur la faute au méchant Microsoft en dédouanant pour sûr le compilo, faudrait pas déconner et se poser des questions.

                    • [^] # Re: Je cherche à comprendre

                      Posté par . Évalué à 4.

                      il a du mal si je m'amuse avec des caractères qui ne sont pas sur la locale de l'OS utilisé (la locale change suivant la région) alors que j'ai des caractère d'un autre endroit (fichier, réseau etc, la j'en chie bien car du coup je n'ai pas la même locale en input et output, et je dois configurer la local de sortie du coup).

                      Je ne comprends pas : si tout le programme est structuré autour des caractères et non des octets (c'est à dire en utilisant wchar_t/std::wstring si l'on utilise que les types C/C++ de base), et que l'on utilise uniquement les fonctions appropriées qui gèrent Unicode (les fonctions *W), alors il n'y a aucun problème sur Windows.
                      Je recommande la lecture d'UTF-8 Everywhere, même s'il n'explique pas les détails pour Windows.

                      • [^] # Re: Je cherche à comprendre

                        Posté par (page perso) . Évalué à 4.

                        Je ne comprends pas

                        Tu as bien raison, je me suis mélangé un peu les pinceaux.
                        J'essaye de reprendre :
                        - Par défaut la ligne de commande n'est pas en UTF-8. Mais une locale 8-bit (histoire, histoire).
                        - Si l'input est avec la même locale, tu ne peux jamais avoir un caractère Unicode pas dans la locale (si tu ne touche pas aux caractères), pas de soucis (wcout convertit dans la locale).
                        - Si ton programme parle la même langue que l’utilisateur, miracle ça marche car la locale 8-bit a tes caractères.
                        - Problème : tu as un caractère qui vient d'ailleurs (exemple : nom de fichier que tu veux afficher, en Russe dans la console sur ton OS français), tu peux faire wcout si tu as envie, la locale est CP-850 et ton russe se fait virer
                        - Ne fantasme pas sur Windows ça pue, sous Linux c'est exactement pareil, j'en ai aussi chié avec Linux quand celui-ci n'est pas en UTF-8 (genre des vieilles RHEL en fr_FR plutôt que fr_FR.UTF-8). La seule différence est que toutes les distros ont aujourd'hui fait le grand saut vers UTF-8, pas Windows.
                        - Du coup, j'ai du "code magique" (pas de moi, on m'a filé l'astuce) : "_setmode(_fileno(stdout), _O_U8TEXT);_setmode(_fileno(stderr), _O_U8TEXT);". Qui fait que le term me file du UTF-8 quelque soit la locale réelle et accepte du UTF-8 quelque soit la locale réelle (il l'affiche même!), tout en mettant du UTF-8 sur les redirections (>fichier, parce que ça fait chier mes utilisateur d'avoir la locale du term dans un fichier texte en 2012). Bref, je configure le term en UTF-8 contre la config de l'utilisateur car Windows sait causer UTF-8 quad on lui demande, c'est jsute que par défaut ça ne l'est pas. Je pourrai sans doute faire pareil sous Les Linux, mais les Linux sans UTF-8 se font rares maintenant (même en embarqué) et donc pas de besoin vraiment.

                        Bref, les merdes de Windows, je connais et je (sur)vis avec. Pas besoin de merdes supplémentaires avec un compilo qui ne sais pas convertir dans la locale de l'utilisateur alors que ce même utilisateur lui a filé la chose juste avant avec exactement la même locale.

                • [^] # Re: Je cherche à comprendre

                  Posté par . Évalué à 3. Dernière modification le 09/06/12 à 20:10.

                  En fait, il semblerait que ce soit le writefln qui pose problème, car "J├®r├┤me" est l'interprétation CP-850 des octets correspondants à "Jérôme" encodé en UTF-8. argv est bien interprété et contient les octets UTF-8 de "Jérôme", et writefln écrit ces octets sans tenir compte de l'encodage de la console.
                  Pourquoi CP-850 alors que la console supporte bien Unicode ? Probablement parce que la variante ANSI de la fonction a été utilisée, et non la variante Unicode. Le problème vient donc de writefln.

                  • [^] # Re: Je cherche à comprendre

                    Posté par . Évalué à 1.

                    En règle générale, std.stdio n'est pas du tout apprécié par la communauté.
                    Apparemment un nouveau module std.io va bientôt(entendre par là quelques mois ou versions) être écrit, à vocation d'être moins buggé(et aussi pour rajouter de nouvelles fonctions mais bon), pour rendre remplacer std.stdio sur le long terme(j'imagine que dans un premier temps il sera marqué deprecated).

      • [^] # Re: Je cherche à comprendre

        Posté par . Évalué à 0.

        Marrant: en lisant ton commentaire, je me suis dit : "Tiens, on dirait du Zenitram"
        Gagné ;-)

    • [^] # Re: Il y a encore du boulot

      Posté par (page perso) . Évalué à 1.

      Bonjour, vous utiliser une très veille version du langage. Je vous conseille d'installer le dépôt debian mentionner dans l'article.

      pour des raisons de vouloir être succins je n'ai pas mis toutes les fonctionnalités de plus la fonction main peut retourner 0, 1 ou autre si vous le souhaiter.
      L'utilisation de scope(exit) par exemple permet de positionner des instructions avant de quitter une fonction. Par exemple fermer un fichier, relacher un mutex …

  • # Est-ce que le langage D possède des bindings stables ?

    Posté par . Évalué à 3.

    Salut !
    J’ai déjà utilisé ce langage et je le trouve super.
    Cependant, dès que j’ai voulu utilisé des bibliothèque venant de d’autres langages, j’ai trouvé que ce n’est pas fameux…
    Je voulais savoir si ça c’est amélioré.
    Je constate, par exemple, que seul GtkD est stable si je me fie à la page dans le wiki bibliothèques GUI.
    Je trouve que ça fait longtemps que cette page indique cela, donc je me demande si les autres bindings sont stables.
    Quand j’avais essayé ce langage, j’avais essayé plusieurs bibliothèques et j’avais seulement réussi à installer GtkD sur mon ArchLinux.
    Pour les autres bibliothèques que j’ai essayées, j’avais eu bien des problèmes…
    C’est pourtant un langage intéressant et j’aimerais bien laisser le C++ pour le D, mais je trouve qu’il manque de maturité pour les bibliothèques GUI.
    J’aimerais bien être éclairé à ce sujet.
    Merci.

    • [^] # Re: Est-ce que le langage D possède des bindings stables ?

      Posté par . Évalué à 3.

      Les bindings les plus utilisables sont, pour moi, GtkD(qui est un wrapper OO, même si vu le manque de doc c'est galère à utiliser) et Derelict2(une collection de bindings dynamiques pour le dev de JV), il y a Derelict3 qui commence à grossir petit à petit mais c'est déjà utilisable. ;)

    • [^] # Re: Est-ce que le langage D possède des bindings stables ?

      Posté par . Évalué à 2.

      Si la quantité des bindings t'importe, mais que tu cherche quelque chose de plus sympatique que le C++, je te conseille le Vala.

      Le Vala étant binairement compatible avec le C, il permet d'utiliser à peu près ce qu'on veut. Attention néanmoins, c'est un langage jeune.

      • [^] # Re: Est-ce que le langage D possède des bindings stables ?

        Posté par . Évalué à 1.

        J’ai déjà essayé le Vala et il est en effet sympathique.
        Cependant, je trouve qu’il a moins de fonctionnalités que le C++, et le D m’a semblé être une alternative intéressante pour moi.
        Mais s’il n’y a pas beaucoup de bindings, je vais continuer à utiliser le C++.

  • # attributes

    Posté par . Évalué à 2.

    La dépêche est bien rédigé, elle présente bien la facilité du langage.
    Seulement, je trouve que la fonction avec les delegate :

    pure size_t f( in size_t delegate(size_t) pure dg1, in size_t delegate(size_t) pure dg2) {
    return dg1( x ) + dg2( x );
    }

    est trop verbeuse, surtout qu'en soit cela n'apporte rien en terme d'optimisations ou autres.
    J'aimerai bien que tu expliques si @safe pure nothrow @trusted @system, apporte quelque chose en terme d'optimisations ou si c'est pour faire joli ? (j'ai jamais compris à quoi ça servait en pratique :d)

    Sinon tu aurais pu parler des templates constraints, des mixin et de la CTFE aussi, c'est quand même les grosses features de D.

    Cool en tout cas,

    • [^] # Re: attributes

      Posté par . Évalué à 2.

      @safe pure nothrow @trusted @system

      J'imagine que ça permet des vérifications statiques ?

      • [^] # Re: attributes

        Posté par (page perso) . Évalué à 4.

        Pour @safe, c'est le cas. Dans la doc, on lit

        Safe func­tions are func­tions that are sta­t­i­cally checked to ex­hibit no pos­si­bil­ity of un­de­fined be­hav­ior. Un­de­fined be­hav­ior is often used as a vec­tor for ma­li­cious at­tacks.

        http://dlang.org/function.html#Safe

        « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

      • [^] # Re: attributes

        Posté par . Évalué à 1.

        Certes, mais en terme d'optimisations ?

  • # Bof

    Posté par . Évalué à 10.

    Je ne suis pas convaincu par cette dépêche : l'effort est louable et je salue l'investissement et le travail accompli, mais je trouve qu'elle passe trop de temps sur les parties peu importantes (je pense que tout le monde sait comment faire une conditionnelle ou une boucle) sans parler des points novateurs du langage.

    Ce que je voudrais savoir c'est, en évitant au maximum la langue de bois : qu'est-ce que ce langage a de différent des autres, d'intéressant ? Dire qu'il vise à faire un C++ plus simple c'est bien, ça donne une idée d'ensemble, mais il faudrait insister plus sur ce point (comment les templates sont-elles simplifiées par rapport à celles de C++ par exemple ?) et moins sur des banalités.

    Par ailleurs le code suivant me donne la nausée :

    pure size_t f( in size_t delegate(size_t) pure dg1, in size_t delegate(size_t) pure dg2) {
    
    

    Sérieusement, le lecteur est-il supposé être attiré par cet exemple ? Moi je le trouve repoussoir et je suis presque un peu vexé qu'on lui trouve un lien avec "la mode fonctionnelle" qui ne propose pas en général d'écrire ces horreurs. N'y a-t-il pas un peu d'optimisation prématurée de la part de l'auteur du code ?

    Enfin je suis amusé par une légère forme de langue de bois en fin de dépêche. Tu dis que le langage "n'est pas propriétaire" (je ne sais pas exactement ce que ça veut dire) mais le paquet conseillé pour Debian est "dmd", un compilo qui est justement propriétaire. Je note aussi que si on va sur la page officielle du langage et qu'on clique sur "téléchargement", on ne se voit proposer que celui-là; c'est bien qu'il existe des implémentations libres à côté mais encore faut-il qu'elles soient à jour, compétitives et utilisées, ce qui reste à prouver. Bref il me semble un peu optimiste (voire autruche) de classer cette remarquer dans la catégorie "mythes et légendes fausses".

    • [^] # Re: Bof

      Posté par (page perso) . Évalué à 5.

      Je plussoie. Le même code que celui donné en exemple de code "fonctionnel" écrit en Haskell :

      main = putStrLn $ show (f inc inc)
        where
          n = 2
          x = 1
          inc k = n + k
          f dg1 dg2 = (dg1 x) + (dg2 x)
      
      

      Et en Scala (qui n'est pas fonctionnel pur) :

      object Main {
        def main(args:Array[String]) {
          val n = 2
          val x = 1
          def inc(k:Int) = n + k
          def f(dg1:Int=>Int,dg2:Int=>Int) = dg1(x) + dg2(x)
          println(f(inc,inc))
        }
      }
      
      

      Je pense qu'il aurait mieux valu dans la dépêche parler des autres avantages de D : Garbage Collector, fin de l'obsolète séparation .h/.c, etc.

    • [^] # Re: Bof

      Posté par (page perso) . Évalué à 4.

      Je ne suis pas convaincu par cette dépêche

      Quand a moi je ne suis pas convaincu par l'utilité des commentaires qui n'ont d'autre but que de dégouter l'auteur de la depeche (zenitram a fait très fort). Personnellement j'ai trouvé cette dépeche très interessante, je me permets de le signaler pour contrebalancer un peu tous vos commentaires négatifs parce que j'aimerais bien en revoir d'autres.

      • [^] # Re: Bof

        Posté par (page perso) . Évalué à 4.

        Je suis d'accord avec toi et vu le score de la dépêche, je ne dois pas être le seul.

        « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: Bof

      Posté par . Évalué à 3.

      Bonjour,

      Je suis d'accord sur le fait que cette présentation n'est pas très réussie, elle passe du temps sur des trucs qui ne font pas l'intérêt du langage (comme les boucles ou les classes), tant en délaissant quantité de choses bien plus intéressantes. Il y en a de bien meilleures sur le net si vous êtes anglophone. Pour ma part, je considère que D est l'un des langages natifs les plus puissants actuellement (si ce n'est LE langage natif le plus puissant).

      Pour ce qui est des delegates, voici un exemple plus intéressant:

      // find est une fonction template qui prend un delegate en predicat
      // le if(is(typeof...)) est une condition sur le prédicat vérifiée par le compilateur
      // celui-ci doit retourner un bool
      // input[1..$] dénote le tableau input[i] pour i = 1 .. length-1
      
      T[] find(alias pred, T)(T[] input)
          if (is(typeof(pred(input[0])) == bool)
      {
        // on raccourcit le tableau d'un elem, ce qui revient à avancer le pointeur *input
        for(; input.length > 0; input = input[1..$]){
          if (pred(input[0])) break; // si le prédicat est vérifié, on s'arrête
        }
        return input;
      }
      
      // exemple d'usage
      unittest{
        int[] a = [1, 2, 3, 4, -5, 3, -4];
        // trouve le premier nombre < 0
        auto b = find!(delegate bool(int x){return x < 0;})(a);
        // idem, notation raccourcie qui tire parti de l'inférence de type
        auto b = find!((x){return x < 0;})(a);
      }
      
      

      Vous voyez dans l'exemple ci-dessus plusieurs notions de D: les templates, les contraintes de signature, les fonctions d'ordre supérieur, et l'inférence de type. C'est la combinaison de toutes les features de D qui en font sa puissance.

      Enfin je suis amusé par une légère forme de langue de bois en fin de dépêche. Tu dis que le langage "n'est pas propriétaire" (je ne sais pas exactement ce que ça veut dire) mais le paquet conseillé pour Debian est "dmd", un compilo qui est justement propriétaire. Je note aussi que si on va sur la page officielle du langage et qu'on clique sur "téléchargement", on ne se voit proposer que celui-là; c'est bien qu'il existe des implémentations libres à côté mais encore faut-il qu'elles soient à jour, compétitives et utilisées, ce qui reste à prouver. Bref il me semble un peu optimiste (voire autruche) de classer cette remarquer dans la catégorie "mythes et légendes fausses".

      C'est inexact. La licence du backend du compilo DMD est propriétaire, mais le frontend est complètement open source. Et on peut contribuer au backend à volonté. La seule chose qui est interdite par la licence, c'est de redistribuer le backend.

      Le source est sur Github
      Quand aux autres compilos, si LDC (LLVM) est fortement en retard, LDC (gcc) est en etard de 2 versions, soit environ 4 mois, sur DMD. Il est parfaitement utilisable et utilisé en pratique.

      • [^] # Re: Bof

        Posté par . Évalué à 4.

        Merci pour ces informations; c'est ce genre de choses que j'aurais bien aimé voir dans une dépêche, un aperçu des fonctionnalités avancées du langage.

        Est-ce que tu pourrais en dire un peu plus sur la signification de alias pred, et pourquoi tu utilises un compile-time test plutôt que de spécifier un type du style delegate bool(T)?

        (Pour ma part je suis un peu gâté; le langage natif que j'utilise permet d'écrire ça plus facilement, depuis un peu moins de 20 ans, donc je dirais plutôt que D rattrape le retard que C, et C++ (au moins avant lambda) ont accumulé vis-à-vis de la programmation fonctionnelle. Mais je suis sûr que D a d'autres avantages, par exemple il paraît qu'il peut être utilisé sans GC, même si je ne suis pas sûr que c'est vraiment praticable.)

        Enfin je suis amusé par une légère forme de langue de bois en fin de dépêche. Tu dis que le langage "n'est pas propriétaire" (je ne sais pas exactement ce que ça veut dire) mais le paquet conseillé pour Debian est "dmd", un compilo qui est justement propriétaire. […] c'est bien qu'il existe des implémentations libres à côté mais encore faut-il qu'elles soient à jour, compétitives et utilisées, ce qui reste à prouver. […]

        C'est inexact. La licence du backend du compilo DMD est propriétaire, mais le frontend est complètement open source. Et on peut contribuer au backend à volonté. La seule chose qui est interdite par la licence, c'est de redistribuer le backend.

        Le backend n'est pas libre, donc le compilateur dans son ensemble n'est pas libre; dire que "le compilateur (officiel) est propriétaire" me semble exact. C'est bien qu'il encourage des gens à réutiliser son frontend, regarder ses sources, etc., mais ça reste un logiciel propriétaire.

        Quand aux autres compilos, si LDC (LLVM) est fortement en retard, LDC (gcc) est en retard de 2 versions, soit environ 4 mois, sur DMD. Il est parfaitement utilisable et utilisé en pratique.

        Quand je disais qu'il "restait à prouver" que les alternatives libres étaient au niveau, je voulais dire que je n'en savais rien (je ne connais pas bien D) et qu'il fallait développer la question au lieu de la traiter d'un ton catégorique sans rien dire: le diable est dans les détails. Merci d'avoir apporté des précisions supplémentaires; chacun jugera comme il voudra les informations.

        Moi ça me gênerait¹ d'utiliser un langage dont l'implémentation principale est propriétaire et dont les concurrents libres doivent "suivre la musique" (en l'absence de spécification du langage et avec une sémantique qui évolue encore régulièrement), mais la situation es quand même raisonnable et je comprends très bien que d'autres gens s'en accommodent. Il n'empêche que j'en retiens que c'est considérablement plus compliqué, comme situation, que de dire juste "ah non c'est un mythe".

        ¹: À mon humble avis il y a déjà assez de langages satisfaisants à l'implémentation libre pour qu'on n'ait pas besoin de jeter son dévolu sur un langage au statut moins clair. Par exemple, si j'étais intéressé par le genre de choses que met D en avant, je pourrais à la place utiliser et soutenir Rust (aussi en développement), ATS (un peu plus orienté recherche), Cyclone (un peu mort), Vala ou même Common Lisp (SBCL) ou OCaml.

        • [^] # Re: Bof

          Posté par . Évalué à 1.

          Est-ce que tu pourrais en dire un peu plus sur la signification de alias pred, et pourquoi tu utilises un compile-time test plutôt que de spécifier un type du style delegate bool(T)?

          L'exemple est tiré de "The D Programming Language" d'A. Alexandrescu. Vous avez raison, delegate bool(T) est plus simple ici, mais c'est juste à titre d'exemple. Mais imaginons une fonction find42 qui cherche la string '42'.

          T[] find42(alias pred, T)(T[] input)
              if (is(typeof(pred(input[0])) == string)
          {
            // on raccourcit le tableau d'un elem, ce qui revient à avancer le pointeur *input
            for(; input.length > 0; input = input[1..$]){
              if (pred(input[0]) == '42') break; // si le prédicat vaut '42', on s'arrête
            }
            return input;
          }
          
          

          alias nom synonyme; où nom peut être n'importe quel symbole compilable, ça peut être une fonction, un type, une valeur, un nom de module…
          Dans find42, alias pred peut être un delegate string(T), mais aussi une string, par exemple.
          Les contraintes if peuvent bien sûr être nettement plus complexes et porter sur les divers paramètres du template.

          À mon humble avis il y a déjà assez de langages satisfaisants à l'implémentation libre pour qu'on n'ait pas besoin de jeter son dévolu sur un langage au statut moins clair. Par exemple, si j'étais intéressé par le genre de choses que met D en avant, je pourrais à la place utiliser et soutenir Rust (aussi en développement), ATS (un peu plus orienté recherche), Cyclone (un peu mort), Vala ou même Common Lisp (SBCL) ou OCaml.

          Le gros avantage de D, outre la syntaxe relativement familière pour les habitués de C++ est son rapport expressivité/performance. ATS a l'air intéressant, mais ne semble maintenu que par une personne. D a maintenant une dizaine de contributeurs très réguliers et une trentaine de contributeurs occasionnels. C'est sans compter les mainteneurs des compilateurs alternatifs. Il y a en moyenne 5 bugs corrigés/jour, sans compter les nouveaux développements. Comme il est développé par des experts du C++ (W. Bright et A. Alexandrescu), ce langage et ses pratiquants sont clairement la cible. Par conséquent, la performance fait partie des buts essentiels.

  • # Premiere impression

    Posté par . Évalué à 5.

    Quand j'ai vu la news, je me suis dit "ah oui tiens, c'est vrai que ça existe,
    j'ai bien envie de voir ce que ça donne sur des exemples".
    Hop, la première chose que je fais, c'est sauter tout le texte pour ne lire que
    les exemples (je sais, c'est pas bien). Et là, je me dis "wow, 4 fonctions différentes
    de type write quelque chose, il doit y avoir vraiment une bonne raison
    pour expliquer cette profusion de fonctions qui semblent faire la même
    chose". Je lis donc le texte, et je ne trouve rien :'(
    C'est sûr que lorsque je serais vraiment motivé pour apprendre ce langage
    je chercherais dans la doc mais là, pour un article introductif je trouve cela très
    rebutant (après, la programmation, ce n'est pas mon métier hein)…
    Bref, j'aurais aimé un peu plus de détails ou bien des exemples qui soulèvent
    moins de questions.

    ++,

  • # rien à dire

    Posté par . Évalué à 1.

    Merci pour cette dépêche, très très intéressante.
    Les commentaires résultant sont tout aussi instructifs !! Merci à vous aussi.

  • # Interrogation

    Posté par (page perso) . Évalué à 6.

    D est-il la réponse ?

    • [^] # Re: Interrogation

      Posté par (page perso) . Évalué à 1.

      Sur le site du langage D, il y a en bannière : «j'ai enfin eu un D en programmation !»

  • # Autres articles

    Posté par . Évalué à 2.

  • # «the D programming language»

    Posté par (page perso) . Évalué à 3.

    Merci pour votre présentation du langage D.

    J'ai récemment acheté le livre: «the D programming language» d' Andrei Alexandrescu.

    Je suis loin d'avoir tout lu, mais il est fort bien écrit et très intéressant.
    Ce n'est pas un simple livre d'initiation, et il semble couvrir complètement le langage tout en restant didactique et d'une taille raisonnable.

    Par contre, je ne saurais dire si il est toujours adapté aux dernières évolutions du D : le livre est paru en 2010. Je serais d'ailleurs intéressé de connaître les choses qui ne sont plus valables dans ce livre.

    • [^] # Re: «the D programming language»

      Posté par . Évalué à 3.

      Il n'y a quasiment rien qui n'est plus valable(et ce n'est pas au niveau des specs du langage, mais de Phobos), néanmoins le livre contient un certain nombre d'erreurs que tu peux consulter ici.

      Depuis le livre grosso modo, je dirai qu'il y a eu l'ajout des UFCSs(je ne suis pas sur mais je pense qu'il les a utilisé dans le livre(avant qu'ils implémentent le truc)), et la nouvelle syntaxe lambda C#-like(on peut utiliser l'ancienne encore) :

      void main()
      {
          auto foo = delegate string(string bar) { return bar; }; // comme dans le livre
          auto foo2 = (string bar) => bar; // une autre possibilité maintenant
          writeln(foo("bar"), foo2("bar2")); // output : barbar2
      }
      
      

      Voilà en gros.

      Sinon depuis le livre ils ont implémenté @property, @safe, alias this est utilisable maintenant(avant y'avait des gros bugs, maintenant y'en a moins), je sais pas ce qu'il en est de inout j'ai encore jamais eu le plaisir de l'utiliser.

  • # Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

    Posté par . Évalué à 6.

    Tout est un peu dans le titre. J'ai l'impression que les devs système sont finalement assez satisfaits de C, et que C++ est difficilement détrônable sur le reste. Quoi qu'il en soit, je retrouve dans D tout un tas de choses que je trouve archaïques, et que seuls les devs C ou C++ comprennent, car ils se sentent à l'aise avec.

    Une première chose est la verbosité des déclarations. Finalement, les histoires de "@safe pure nothrow" ne sont que des commandes d'optimisation, que l'on utilise principalement pour aider les compilos. Je ne suis pas certain que ça soit au programmeur de gérer ça. La raison principale est que, selon mon expérience, ça nuit à l'évolution et à la flexibilité du programme. Je ne connais pas assez D, mais en C++, on se tape des arbres super-complexes de const à gérer ; modifier le status "const" d'une variable est quasiment impossible dans un programme complexe, le compilo hurle avec des milliers de messages d'erreur, et on finit par saloper le design avec des mutable, et/ou par dupliquer toutes les méthodes avec une version const et une version non-const strictement identiques. Je pense que les langages doivent aussi être conçus pour les gens qui ne sont pas des experts en programmation, y compris en évitant au maximum de faire faire le boulot du compilo aux programmeurs.

    L'autre truc qui me fait vraiment reculer, c'est le fait que les tableaux sont gérés comme en C comme des pointeurs. Alors oui, c'est élégant et rapide, mais ça demande un mode de réflexion qui n'est pas naturel pour la plupart des gens, ça rend le code lourd, et surtout, ça induit un mode de programmation basé sur les boucles (indentations récurrentes, définition de variables temporaires qui s'appellent "i" ou "x" et qui ne sont parfois pas réutilisées… Alors c'est sûr, on a toujours tout un tas de bibliothèques externes qui implémentent des vecteurs et des matrices, mais, à mon avis, la présence de ces bibliothèques ne fait que confirmer le manque de gestion des structures simples par le langage (sans comper que l'utilisation correcte de la STL nécessite une expertise assez hallucinante).

    Typiquement,

    int tab[] = [1, 2, 3];
    tab = tab + 1;

    signifie, pour un être humain normal, [2,3,4]. Alors oui, c'est certain, un cerveau est assez flexible pour comprendre que ça n'est pas le cas et d'apprendre comment faire une boucle à la place, mais je ne comprends pas comment on peut encore se retrouver avec des langages qui ne gèrent pas intuitivement la concaténation de caractères

    string toto = "Mon prénom est " + "Toto";

    ou la manipulation de vecteurs

    double moy = sum(tab)/size(tab);

    Je me demande s'il n'y a pas un peu d'obfuscation volontaire de la part des gens qui créent et utilisent des langages basés sur des concepts qui ont 30 ou 40 ans, et qui, finalement, sont bien contents de se sentir supérieurs grâce à leur compréhension intuitive des std::const_iterator<std::vector<double> > obj.begin(). On crée D, E, F, G, H ou I avec la volonté d'être moins verbeux, mais finalement, on ne fait que changer le langage en laissant les habitudes inchangées.

    • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

      Posté par . Évalué à 3.

      C++ est beaucoup trop complexe comme langage; si les gens de D arrivent à faire un langage presque aussi utile et beaucoup moins complexe, ce sera un gain énorme. Et ça a des chances de se passer comme ça vu les gens qui bossent sur ce langage (Alexandrescu par exemple). C'est à mon avis le principal intérêt du langage.

      Après pour la gestion "propre" de la concurrence, je demande à voir mais pourquoi pas, ça pourrait marcher. Les modifieurs @safe, pure et nothrow ne devraient pas être utilisés à toutes les sauces mais seulement quand c'est utile (si on veut les utiliser plus il faut une syntaxe qui permette de ne pas les répéter systématiquement). La difficulté est de pouvoir laisser les programmeurs experts s'en servir sans imposer un coût en complexité important aux non-experts (qui doivent pouvoir les ignorer ou presque) tant qu'ils n'essaient pas de faire quelque chose de difficile (là il faut se former). C++ ne réussit pas bien à cacher la complexité de ses fonctionnalités avancées, d'autres langages le font mieux, D pourrait y arriver.

      • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

        Posté par . Évalué à 3.

        C'est clair qu'à la place de supprimer la complexité, on peut simplement la cacher. Mais regarde le main() de D : on a déja un string[]. C'est mieux qu'un char** (!!!), mais on ne récupère pas non plus quelque chose de manipulable : par exemple, que donne un writeln(args)?

        Ceci dit, c'est peut-être aussi que les exemples choisis sont étranges. Ces types size_t semblent très mystérieux, et le premier exemple propose déja des immutable et des pure nothow, alors que ces mots-clé ne sont peut-être pas indispensables ici?

        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

          Posté par (page perso) . Évalué à 2.

          oui je suis d'accord l'article est bref et ne développe c'était avant tout de faire une première aproche en essayant de satisfaire ceux qui ont jamais vu du D et ceux quelque fois.

          Le type size_t est un alias vers uint ou ulong selon que l'on se trouve en 32 ou 64 bits. Je l'ai volontairement utilisé abusivement pour marqué que ce type existe. La taille d'un tableau est de size_t.max ainsi lorsque l'on manipule des tableaux il vaut mieux utilisé size_t .

          pour ce qui est de args :

          import std.stdio;
          
          void main( string[] args ){
              writeln(args);
          }
          
          
          $ ldc2 cmd.d
          $ ./cmd 
          ["./cmd"]
          $ ./cmd je test une longue phrase
          ["./cmd", "je", "test", "une", "longue", "phrase"]
          
          
        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

          Posté par . Évalué à 4.

          La dépêche ne présente pas bien D et ses avantages, c'est un fait. Pour avoir une idée de la comparaison réelle entre D et C++, tu peux par exemple regarder les réponses à cette question : Stackexchange: What does C++ do better than D?

    • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

      Posté par (page perso) . Évalué à 2. Dernière modification le 11/06/12 à 15:12.

      les attributs @xxxx permettent de mettre en place des optimisations pour le compilateur qui ne sont pas détectable ou pas facilement. Certains d'entre eux permettent de garantir la fiabilité de la fonction rendant le programme finaux plus sûre, la sécurité des applications est un gros problème en programmation.

      Ce n'est justement pas un langage avec des idées de 30 - 40 ans. Voici un court script pour effectuer les opérations décrites ci-dessus. A noter que les opérations utilisant map et reduce sont parallélisées.

      import std.string;
      import std.stdio;
      import std.algorithm;
      import std.array;
      import std.typecons;
      import std.math;
      
      void main( string[] args ){
          int[] tab   = [-1, 0, 1, 2, 3];
          tab         = array(map!("a + 1")(tab));
          writeln( tab );
          size_t moyenne = reduce!("a + b")(0, tab) / tab.length;
          writefln( "La moyenne est de %d", moyenne);
      
          auto r = reduce!("a + b", "a + b * b")(tuple(0, 0), tab);
          writefln( "somme: %d | somme des carées: %d | moyenne: %d |  écart type: %f",
                                                                                          r[0],
                                                                                          r[1],
                                                                                          r[0] / tab.length,
                                                                                          sqrt(cast(float)(r[1] / tab.length - moyenne * moyenne))
                                                                                          );
          string toto = "Mon prénom est " ~ "Toto";
          writeln(toto);
          string toto2 = "Mon prénom est %s".format( "Toto" );
          writeln(toto2);
      }
      
      
      [0, 1, 2, 3, 4]
      La moyenne est de 2
      somme: 10 | somme des carées: 30 | moyenne: 2 |  écart type: 1.414214
      Mon prénom est Toto
      Mon prénom est Toto
      
      
      • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

        Posté par . Évalué à 2.

        size_t moyenne = reduce!("a + b")(0, tab) / tab.length;
        
        

        Ah ouais, c'est limpide comme syntaxe. C'est exactement le même brainstorm que la STL C++ : un truc potentiellement puissant mais illisible.

        Ma critique, c'était justement que le langage soit apporter un minimum de fonctions de base. Bien sûr qu'on peut recalculer une moyenne ou une variance à la main, on peut même créer des méthodes pour le faire, on peut même créer sa propre bibliothèque de gestion de vecteurs, avec des vector_int, vector_double, ce qui permettrait de faire des vec.sum() et des vec.mean(). Mais on s'en fout, ce qui est crucial, c'est que le langage vienne avec ça, parce que ça fait partie de ce qu'on fait tous les jours avec des vecteurs. Là, le langage vient tout nu, c'est un truc McGyver. À chaque début de projet, tu réinventes la roue, avec éventuellement des bugs ou des problèmes de performance. Ça me semble totalement inutile, et en plus c'est illisible.

        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

          Posté par . Évalué à 2.

          Ce sont des langages système, donc de bas niveau.

          Si vous voulez les fonctionnalités de Python ou de Matlab, faites du Python ou du Matlab. Les langages C/C++/D ne sont pas faits pour manipuler des vecteurs (au sens mathématique), il sont faits pour manipuler des éléments en mémoire.

          Le D est nettement plus lisible que le C++.
          Sinon, pour l'exemple ci-dessus, il n'a rien d'effrayant, vous pouvez parfaitement en faire une fonction moyenne, et vous remarquerez que vous pouvez définir une fonction intégrale de la même manière:

          auto integrale = integrate!("sin(x)")(0, Pi);

          A part le '!', difficile de faire plus simple.

          • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

            Posté par . Évalué à 2.

            Ce sont des langages système, donc de bas niveau.

            C'est exactement le sens de ma remarque. D ne sera probablement jamais utilisé pour coder un système d'exploitation ou un pilote de périphérique. Si on regarde l'utilisation de C++, c'est principalement du logiciel utilisateur (bureautique, logiciels spécialisés, etc). Dans mon domaine, le C et le C++ sont utilisés principalement pour coder des modèles "maison" (simulations, etc) quand les langages haut niveau sont trop lents. Au passage, matlab est un peu déprécié en biologie, les gens préfèrent de plus en plus R.

            Les langages C/C++/D ne sont pas faits pour manipuler des vecteurs (au sens mathématique)

            Les vecteurs de caractères ou de chaines de caractères n'a aucun sens mathématique, et pourtant, ils sont manipulés par le langage.

            Le problème, à mon avis, ne vient pas vraiment du "niveau" du langage, mais du présupposé sur l'utilisation qui en est faite. Un langage bien foutu devrait pouvoir être utilisé par tout type d'utilisateur, et ce n'est pas le cas, ni pour C, ni pour D. Quelqu'un qui veut faire des choses très simples ne devrait pas avoir à récupérer un char** en argument du main() (en gros, on devrait pouvoir utiliser le langage sans pointeurs), et la librairie standard devrait permettre tout un tas d'opérations de base sans avoir à les recoder soi-même : min(), max(), sum(), mean(), il me semble un peu ridicule de passer par une STL (ou équivalent) pour des opérations aussi triviales.

            • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

              Posté par . Évalué à 2.

              L'avantage de passer par une lib telle que la STL, c'est de pouvoir utiliser tout ces algos "de base" avec des opérateurs personnalisés, ce qui est bien pratique quand on veut trier des choux-fleurs. A moins que tu ne saches proposer un opérateur de comparaison universel qui donne le résultat que je veux quel que soit le type que je crée (hint: OCaml fait presque ça avec son compare, sauf que ça ne permettra généralement pas d'avoir l'ordre qui me semble le plus pertinent).

              • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                Posté par . Évalué à 1.

                A moins que tu ne saches proposer un opérateur de comparaison universel qui donne le résultat que je veux quel que soit le type que je crée

                Ce n'est pas possible en général (l'ordre dépend de la sémantique de la structure; le cas d'école étant les arbres balancés qui ne sont pas "canoniques", ie. deux arbres à la structure différente peuvent en fait représenter le même ensemble (balancé différemment), donc tu veux que la comparaison les considère comme égaux).

              • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                Posté par . Évalué à 2.

                L'avantage de passer par une lib telle que la STL, c'est de pouvoir utiliser tout ces algos "de base" avec des opérateurs personnalisés, ce qui est bien pratique quand on veut trier des choux-fleurs.

                C'est sûr, mais (i) est-ce que ça arrive si souvent que ça de vouloir trier ou additionner des choux-fleurs, par rapport à trier ou additionner des nombres ou des chaines de caractères, et (ii) techniquement, je ne vois que peu d'exemples où on veut réellement trier des choux-fleurs selon leur chou-fleuritude : on veut les trier selon leur taille, selon leur couleur, selon tout un tas de trucs qui s'expriment par leur valeur numérique.

                Après, je ne critique pas l'existence d'une STL, qui reste un outil utile dans des cas assez spécifiques. Ce que je critique, c'est le paradigme de programmation qui consiste à faire des appels non-standard à des fonctions triviales dont tout le monde a besoin, et qui elles font des appels à la bibliothèque standard.

                Par exemple, M. Dupont va programmer une fonction somme(iterator, iterator) qui va appeler std::accumulate; alors que M. Smith va programmer une fonction sum(vector) qui va appeler std::accumulate. Bref, les deux ont les mêmes besoins, ils appellent les mêmes fonctions standard en arrière plan, mais leur interface n'est pas standard. Ça duplique les efforts, ça rend le code plus difficile à maintenir et à lire, les fonctions résultantes ont peut-être des bugs ou elles ne sont peut-être pas optimales. Je ne vois pas du tout l'intérêt d'intercaler les couches de trucs standard et de trucs non-standard.

                Il est évident que si la bibliothèque standard possède des fonctions min() ou sum(), elles ne vont pas toujours se comporter comme le programmeur souhaiterait qu'elles se comportent. Dans ce cas, il faudra de toutes manières repasser par la STL ou équivalent, avec un commentaire du style // je veux le plus petit élément qui ne soit pas 0, alors que la fonction min() renvoie 0. Mais dans 95% des cas, ces fonctions se comporteront exactement comme il faut, et ça fera gagner un temps fou à tout le monde. Je trouve déraisonnable d'estimer qu'un programmeur sur un langage bas-niveau n'a que ça à faire que de chercher dans la littérature l'algorithme optimal pour réaliser telle ou telle tâche triviale.

                • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                  Posté par . Évalué à 1.

                  La STL possède std::min_element, donc on peut faire des min de manière tout à fait standard, et pour comparer n'importe quoi (et ça sert vraiment en pratique, rien que pour implémenter un ordre lexicographique entre deux critères de tri possibles).

                  On peut arguer qu'il manque un sum, effectivement, mais c'est pas non plus super dur d'en écrire un (ça tient en une ligne en C++11 avec un for_each), et j'espère que peu de gens font des erreurs pour coder ça, sinon c'est qu'il y a vraiment un problème.

                • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                  Posté par (page perso) . Évalué à 2.

                  La bibliothèque standard Phobos possède évidement une fonction pour calculer la valeur min ou la valeur max mais en plus elle fournit un module std.algorithm permettant d'obtenir suffisamment de souplesse et de performance pour faire ce que l'on veux. Par exemple si tu veux filtrer le résultat de la valeur min afin qu'elle soit supérieur à 0 utilise la fonction filter (suit le lien pour voir les exemples)

          • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

            Posté par (page perso) . Évalué à 3.

            C++ n'est pas un langage bas niveau. C'est un ensemble d'outils haut-niveau, qui permettent un haut niveau d'abstraction.

            C++ est justement équipé de fonctionnalités permettant de manipuler des vecteurs mathématiques. Le type std::complex est un premier pas dans ce sens.
            http://www.cplusplus.com/reference/std/complex/

            Et Boost, en proposant ses octonions qui font pleurer, achève de te clouer :-D

            D'ailleurs, la dernière mouture de C++ montre l'effort pour rendre encore moins prépondérant le côté « programmation système ». Par exemple, en encapsulant la fabrications de pointeurs intelligents (template make_shared())

    • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

      Posté par (page perso) . Évalué à 3.

      La plupart des opérations n'ont pas besoin d'un opérateur particulier. Pour la concaténation de chaîne et la création de tableau, je trouve plus lisible d'avoir quelquechose comme:

      string toto = "Mon prénom est ".append("Toto");
      array<int> tableau = new array<int>( 1, 2, 3 );
      
      

      http://devnewton.bci.im

      • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

        Posté par (page perso) . Évalué à 4. Dernière modification le 11/06/12 à 15:37.

        Je me permet de rebondir sur ton commentaire. En D tu as une méthode qui permet d'ajouter des éléments a un tableau par une syntaxe similaire a ce que tu décris. L'avantage c'est qu'elle est plus efficace qu'une suite de concaténation.

        import std.stdio;
        import std.array;
        
        void main( ){
            int[] a = [0, 1, 2];
            auto app = appender(a);
            app.put(3);
            app.put(4);
            app.put(5);
            app.put([6,7,8,9]);
            a = app.data;
            writeln( a );
        }
        
        
        $ ldc2 tab.d
        $ ./tab 
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        
        
      • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

        Posté par (page perso) . Évalué à 4.

        string toto = "Mon prénom est ".append("Toto");

        Je ne suis pas fan de cette syntaxe qui devient très lourde quand on a plusieurs éléments à concaténer.

        sting name = "Toto"
        string toto = "Bonjour ".append(name).append(". Vous avez ").append(3).append(" nouveaux messages");
        
        

        comparé à

        string name = "Toto"
        string toto = "Bonjour " + name + ". Vous avez " + 3 + " nouveaux messages");
        
        

        « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

          Posté par . Évalué à 3.

          Je crois me souvenir que D a des formats printf vérifiés statiquement, donc on s'en moque. De toute façon la concaténation successive de chaînes c'est très suspect, algorithmiquement, comme opération (si tu n'as pas des ropes/cordes ou d'escape analysis ça devient vite quadratique).

          • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

            Posté par . Évalué à 3.

            la concaténation successive de chaînes c'est très suspect, algorithmiquement, comme opération

            C'est dommage que les gens en aient besoin, hein.

            • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

              Posté par . Évalué à 4. Dernière modification le 11/06/12 à 19:30.

              Ben non, justement; si au lieu de formuler le code plus haut comme une série de concaténations tu l'écris comme un sprintf, la fonction de formatage peut calculer la taille des différents éléments et allouer une seule chaîne correspondant au résultat final. Ce n'est qu'un exemple, il y a d'autres structures de données (comme les "ropes" citées dans mon précédent message) qui permettent la concaténation en temps constant ou logarithmique plutôt que linéaire (comme c'est le cas avec l'implémentation naïve des chaînes si on ne s'autorise pas à les modifier après création).

              Dans tous les cas, concaténer des chaînes en séries n'est pas réellement un besoin, mais un moyen d'obtenir un résultat final, souvent moins bon que d'autres moyens d'arriver au même résultat.

              • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                Posté par . Évalué à 4. Dernière modification le 11/06/12 à 19:55.

                Dans tous les cas, concaténer des chaînes en séries n'est pas réellement un besoin, mais un moyen d'obtenir un résultat final, souvent moins bon que d'autres moyens d'arriver au même résultat.

                Je suis désolé, mais la clarté du code est un besoin, qui d’ailleurs prime souvent sur les performances brutes dans le cahier des charges.

                • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                  Posté par . Évalué à 4.

                  Et alors, en quoi concaténer des chaînes en série est-il plus lisible qu'un printf ou une interpolation de chaînes ?

                  • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                    Posté par (page perso) . Évalué à 3.

                    Parce que ça demande de compter les arguments pour savoir où on en est et qu'on facilement en louper quand on essaye de savoir lequel correspond à quoi. Par exemple :

                    string name = "Toto"
                    string toto = sprintf("Bonjour %s. Vous avez %i nouveaux messages",name, 3);
                    
                    

                    Quand on lit le %i, il faut interrompre la lecture pour trouver à quoi il correspond. Avec 2 arguments, ça va, c'est quand il y en a plusieurs que ça pose des problèmes.

                    « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

                    • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                      Posté par (page perso) . Évalué à 3.

                      La concaténation de chaîne est un ennemi mortel, qui rend le code illisible, en réduit la maintenabilité, et empêche une gestion efficace de l'internationalisation. Même en PHP je l'ai banni, car son usage entraîne des trous de sécurité systématiques (oublie de l'usage des fonctions de sécurisations des données, entre autres).

                      Ce que tu regrette, c'est le système de formatage historique introduit par le bibliothèque C. Mais si tu regardes, de nombreux langages ont proposé une syntaxe qui permet d'auto-documenter le formatage. Comme c'est le cas en Python.

                      • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                        Posté par . Évalué à 1.

                        string toto = sprintf("Bonjour %s. Vous avez %i nouveaux messages",name, 3);
                        
                        
                        toto << "Bonjour " << name << ". Vous avez " << 3 << " nouveaux messages.";
                        
                        

                        Franchement, tu trouves la première plus lisible? Et de toutes manières, même à lisibilité égale, l'inférence de type est un avantage indéniable (recourir au programmeur pour une tâcha automatisable n'a aucun intérêt).

                        D'ailleurs, j'imagine que la deuxième instruction peut être algorithmiquement transformée vers la première par le compilo. C'est donc le langage qui impose une construction lourde.

                        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                          Posté par . Évalué à 8.

                          toto = "Bonjour ${name}. Vous avez ${3} nouveaux messages"
                          
                          
                        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                          Posté par (page perso) . Évalué à 2.

                          Oui je trouve ça beaucoup plus lisible. À noter qu'ici tu as utiliser un outil encore plus pourave que la concaténation de chaines : l'opérateur d'injection. C'est une horreur totalement illisible, qui rend la compréhension du code tout à fait fatigante.
                          Avec une chaîne de format (qui sera utilisé par l'outil de localisation), on peut se concentrer sur la manière de formater le texte, puis de décider quelles données fournir.

                          Au fait, l'opérateur d'injection n'est pas disponible pour les std::string, mais pour les std::stringstream.

                          Mais n'étant pas un sauvage, j'utilise boost::format depuis un moment.

                          std::cout << boost::format("Bonjour %s. Vous avez %i nouveaux messages\n")
                              % name % 3 ;
                          
                          

                          D'ailleurs, les Variadic Tuples vont te donner la migraine sur ce point. Herb Sutter montre un exemple d'application de VT qui concerne justement une écriture de de print type-safe http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/C-11-VC-11-and-Beyond

                          Ta critique sur l'inférence de type est risible. C'est une chaîne de formatage, ce qui implique qu'on formate la sortie. La précision du type est historique, mais on peut aussi vouloir préciser la précision, compléter le nombre, etc. Je sais bien que les stream permettent ça : mais c'est bien là tout le soucis de lisibilité qui pointe le bout de son nez. Là où il faut 4 caractère pour indiquer un format pour afficher un nombre sur trois digit, il faut tout d'un coup configurer le flux à la volée. En première instance, c'est magique. Mais à l'usage, c'est pénible et illisible.

      • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

        Posté par . Évalué à 2.

        En D, la concaténation de chaîne est encore bcp plus simple: "Hello"~" world"

    • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

      Posté par . Évalué à 6.

      Typiquement,

      int tab[] = [1, 2, 3];

      tab = tab + 1;

      signifie, pour un être humain normal, [2,3,4]. Alors oui, c'est certain, un cerveau est >assez flexible pour comprendre que ça n'est pas le cas et d'apprendre comment faire une boucle à la place

      Pas besoin de faire une boucle :
      int[] array = [1, 2, 3];
      array[] = array[] + 1; // [2, 3, 4]

      C'est joli hein ? :D

    • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

      Posté par (page perso) . Évalué à 1.

      [quote]Une première chose est la verbosité des déclarations. Finalement, les histoires de "@safe pure nothrow" ne sont que des commandes d'optimisation, que l'on utilise principalement pour aider les compilos. Je ne suis pas certain que ça soit au programmeur de gérer ça. La raison principale est que, selon mon expérience, ça nuit à l'évolution et à la flexibilité du programme. Je ne connais pas assez D, mais en C++, on se tape des arbres super-complexes de const à gérer ; modifier le status "const" d'une variable est quasiment impossible dans un programme complexe, le compilo hurle avec des milliers de messages d'erreur, et on finit par saloper le design avec des mutable, et/ou par dupliquer toutes les méthodes avec une version const et une version non-const strictement identiques. Je pense que les langages doivent aussi être conçus pour les gens qui ne sont pas des experts en programmation, y compris en évitant au maximum de faire faire le boulot du compilo aux programmeurs.[/quote]

      Tout dépend des contraintes et de l'exigence que tu as sur ton projet. Si tu t'en fou de savoir qu'une fonction ne lance jamais d'exception, tu te balances donc de savoir si ton programme sera stable. Si en C++, et visiblement en D, on indique la capacité à lancer des exceptions (et lesquelles), c'est pour garantir un contrat. C'est très important pour une fonction utilisée dans un destructeur, par exemple. Et ça, le compilateur ne peut pas le deviner tout seul lors de la compilation de la fonction.

      Je suis d'accord que la gestion des capacités const et non-const est parfois galère. Mais il ne faut pas oublier que, si une fonction membre const modifie l'objet sur lequel elle est appelée, il y a peut-être un problème de design.

      Enfin, si tu as deux fonctions au contenu identique, et que la seule différence est ça constness, c'est que tu ne connais pas cette méthode :

      Ret const & Object::get() const
      {
         return m_something ;
      }
      
      Ret Object::get()
      {
          return const_cast<Ret &>(const_cast<Object *>(this)->get()) ;
      }
      
      

      Comment ça la seconde fonction est illisible :D

      • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

        Posté par (page perso) . Évalué à 2. Dernière modification le 12/06/12 à 07:39.

        Si en C++, et visiblement en D, on indique la capacité à lancer des exceptions (et lesquelles), c'est pour garantir un contrat.

        Il me semble que les compilateurs C++ utilisent ces infos pour optimiser, pas pour faire de la vérification — il y a d'ailleurs une exception bad_exception qui signale les exceptions non prévues!

        C'est très important pour une fonction utilisée dans un destructeur, par exemple. Et ça, le compilateur ne peut pas le deviner tout seul lors de la compilation de la fonction.

        Théoriquement rien n'empêche le compilateur de le savoir, mais il faudrait avoir une notion de fichier objet pour les headers — pour retenir l'information calculée — qui devraient être distribués avec les bibliothèques. (Il faut connaître le header et le code pour faire la déduction correcte.)

        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

          Posté par . Évalué à 4.

          Théoriquement rien n'empêche le compilateur de le savoir, mais il faudrait avoir une notion de fichier objet pour les headers — pour retenir l'information calculée — qui devraient être distribués avec les bibliothèques. (Il faut connaître le header et le code pour faire la déduction correcte.)

          Et, surprise, cette "information calculée" serait une version compilée des marqueurs pure et nothrow dont les gens disaient du mal plus haut. Ça revient exactement à faire de l'inférence de ces marqueurs; et alors pourquoi ne pas laisser aussi l'utilisateur les ajouter explicitement s'il le souhaite ? C'est plus flexible et ça n'enlève rien.

        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

          Posté par (page perso) . Évalué à 2.

          Ce qui te semble est faux : http://www.gotw.ca/publications/mill22.htm

          Rien n'empêche le compilateur de le savoir ?

          // dude.cpp
          // c++ -o dude{,.cpp} -Wall -pedantic -std=c++0x
          #include <iostream>
          #include <stdexcept>
          #include <memory>
          
          struct People
          {
              virtual void joke() throw() = 0 ;
          } ;
          
          struct SkinHead
              : People
          {
              virtual void joke() throw() ;
          } ;
          
          struct Dude
              : People
          {
              virtual void joke() throw() ;
          } ;
          
          int main()
          {
              std::shared_ptr<People> arse { new SkinHead } ;
              arse->joke() ;
          }
          
          void SkinHead::joke() throw()
          {
              throw std::logic_error("Racist joke") ;
          }
          
          void Dude::joke() throw()
          {
              std::cout << "The usual thing\n" ;
          }
          
          

          Si les définitions des fonctions membres ne sont pas dans la même unité de compilation, le compilateur ne pourra pas deviner que People::joke ne lancera jamais d'exception.

          • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

            Posté par (page perso) . Évalué à 4.

            Mais justement,

            void SkinHead::joke() throw()
            {
                throw std::logic_error("Racist joke") ;
            }
            
            

            ne devrait pas pouvoir compiler. Je trouve la manière de faire de Java bien mieux foutue pour les exceptions.

            « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

          • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

            Posté par (page perso) . Évalué à 2.

            Si les définitions des fonctions membres ne sont pas dans la même unité de compilation, le compilateur ne pourra pas deviner que People::joke ne lancera jamais d'exception.

            Et d'une

            void SkinHead::joke() throw()
            {
                throw std::logic_error("Racist joke") ;
            }
            
            

            ne devrait pas compiler (si C++ était mieux fichu), et de deux, c'est quoi qui empêche le compilateur d'écrire dans le fichier objet la liste des exceptions lancées par les fonctions de l'unité de compilation? Rien si ce n'est la flemme.

            • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

              Posté par . Évalué à 2.

              Peux tu éclairer ma lanterne sur pourquoi

              void SkinHead::joke() throw()
              {
                  throw std::logic_error("Racist joke") ;
              }
              
              

              ne devrait pas compiler?

              • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                Posté par (page perso) . Évalué à 3.

                Ben parceque throw() veut dire cette fonction ne lance aucune, absolument aucune exception, ce qui visiblement n'est pas le case. La définition du langage (en tout cas, Stroustrup) demande de compiler mais de lancer bad_exception dans ce cas… Du coup au lieu d'avoir un message utile à la compilation ­— qui aide à écrire des message corrects, on se retrouve avec une exception lancée pendant l'éxécution, qui ne sait pas d'où elle vient. Pratique.

                • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                  Posté par (page perso) . Évalué à 3.

                  La signature throw() ne veut pas dire qu'aucune exception ne sera pas levée dans la fonction, mais garanti qu'aucune exception ne sera émise par la fonction. En l'occurrence, std::terminate sera appelé si une exception tente de s'échapper de la fonction-qui-ne-peut-lever.

                  Ceci sert quand on écrit des fonction exception-safe. C'est une garantie qu'il faut fournir, par exemple, dans les fonctions utilisées par le destructeur virtuel d'une classe.

                  Je partage l'avis que le compilateur devrait râler sur ce cas précis, et honnêtement, avant d'écrire l'exemple, je pensais qu'il le fait. Mais ce n'est pas un problème du langage : c'est un problème du compilateur. Si ça se trouve, LLVM ou MSC++ émettent un warning, peut-être que GCC a une option pour ça qui n'est pas incluse avec -Wall.

                  • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                    Posté par (page perso) . Évalué à 5.

                    Mais ce n'est pas un problème du langage

                    Si, c'est parce que le langage le permet que les compilateurs ne râlent pas.

                    « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

                    • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                      Posté par (page perso) . Évalué à 0.

                      Le langage permet beaucoup, beaucoup de choses. D'ailleurs, en C++, nombres de comportements sont indéfinis. Le plus des compilateurs, s'est de détecter et d'avertir le développeur. Quand j'ai commencé à développer il y a dix ans, le compilateur de détectait pas le renvoie d'un pointeur ou d'une référence sur une variable de portée locale. Aujourd'hui, G++ fait un gros warning qui fait tout péter quand tu compile correctement (-Wall -Werror).

                      • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                        Posté par (page perso) . Évalué à 5.

                        Le langage permet beaucoup, beaucoup de choses.

                        C'est la critique justement, il permet des choses qu'il ne devrait pas.

                        « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

                        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                          Posté par (page perso) . Évalué à 1.

                          Et pourquoi ne le devrait-il pas ?

                          Si le langage laisse des libertés au compilateur, à l'implémentation, au système d'exploitation, c'est pour de bonnes raisons : c'est au développeur de décider ce qui est important. Certains développements ont besoin de fiabilité, d'autres d'être prédictifs, d'autres rapides, d'autres peu gourmand en ressources, et certains exigent de la précision là où d'autres se contente d'une approximation grossière.

                          Un bon exemple est la différence entre les nombres décimaux et les nombres à virgule flottante. Tu n'es pas sans savoir que, de base, C++ ne fournit pas de nombres décimaux. Car non, les nombres à virgule flottante ne sont pas des nombres décimaux. Ce sont des nombres binaires composites, qui contiennent un entier et un exposant (éventuellement un signe de positivité). Les calculs sur ces nombres sont approximatifs et ne sont pas fiables. Par exemple, on ne compare jamais un flottant à 0., mais quelque chose dans ce genre :

                          bool const float_equals_zero(float const number)
                          {
                              return(number > 0. && number < std::numeric_limits::epsilon())
                                  || (number < 0. && number > - std::numeric_limits::epsilon()) ;
                          }
                          
                          

                          Dans une application de jeu vidéo en 3D, c'est bienvenue, car les calculs sur les flottant sont rapides. Y substituer des nombre décimaux en créant un type Decimal serait très malvenu. A contrario, dans une application bancaire, où la précision prime sur la rapidité d'exécution, on utilisera évidement des nombres décimaux.

                          Ensuite, on peut parler du scandaleux comportement de Linux, qui pratique l'overcommit memory. Encore une fois pour de basses considérations sur les performances, le noyau répond au processus qu'il a réservé la mémoire parce qu'il le peut. Mais jusqu'à ce que l'utilisation de la mémoire par l'application ne soit véritablement effectuée, Linux ne lui en réserve pas. Du coup, si dans le temps entre le moment où l'application a réservé de la mémoire, et le moment où elle écrit dedans, Linux n'a plus de mémoire à distribuer, elle tue le processus. Et là, ce n'est même pas une largesse qu'offre à Linux le C, POSIX, ou que sais-je comme autre norme : c'est une optimisation système qui privilégie la rapidité à la fiabilité.

                          Et nous finirons par évoquer la grande guerre des bases de données. Depuis quelques années, on a vu l'émergence d'une « nouvelle » race de base de données : les noSQL. Il y a dans ces technologies récentes plusieurs éléments qui les distingues des SGBDR dites classiques : elles renient SQL (car parser du SQL, ça prend du temps), elles ne garantissent plus le succès d'une opération et ne communiquent pas sur les échecs (ou de manière étrange, comme dans MongoDB, où on est averti de l'échec de la précédente opération). Là encore, il y a eu des compromissions avec la sécurité des données.

                          Je pourrais longuement continuer le catalogue des compromis effectués dans toutes ces technologies. J'ai longtemps été très rétif à toutes ces largesses. Mais depuis que j'ai touché à des architectures ou la scalabilité était primordiale, je me suis rendu compte à quel point c'était une posture idéologique en conflit avec la réalité.

                          C'est pour ça que je défends le choix des concepteurs de C++ de laisser le choix aux développeurs : on ne peut pas tout prévoir, et quand on essaye, on ferme des portes. Avec Java, l'exemple qui m'est le plus criant, c'est la GUI historique : certes, c'est a priori une bonne idée, mais dans les faits, on se coltine des interfaces laides et non-intégrées dans l'environnement graphique de l'hôte. Et surtout, il n'est pas possible de créer des éléments originaux puisqu'on a pas accès à la sous-couche de manière portable.

                          • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                            Posté par (page perso) . Évalué à 5.

                            Je ne comprend pas du tout le rapport entre ce que tu dis et le sujet du thread. On parle du fait que

                            void plop() throw() {
                               throw std::exception();
                            }
                            
                            

                            ne devrait pas être possible. Ce n'est pas une histoire de compromis. Le compromis, c'est le fait de pouvoir écrire throw() ou non pour dire qu'on veut gérer les exception ou non.

                            « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

                            • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                              Posté par (page perso) . Évalué à 1.

                              Ce que tu ne veux pas comprendre, c'est que la signature throw() indique que la fonction sur laquelle elle s'applique ne lancera jamais une exception. Ça ne veut pas dire que les fonctions appelées par la dite fonction son garanties exception-free. Ce qui est garanti, c'est que l'exception n'ira pas plus loin.

                              C'est une garantie, importante quand on écrit du code safe-exception.

                              Et une chose que tu ne comprends pas non-plus, c'est que C++ conserve une compatibilité avec C. Et les fonctions C, elles ne savent pas ce qu'est une exception.

                              Si tu ne veux pas gérer les exceptions, le compilateur propose une option pour ça.

                              Comme je l'ai dit plus haut, Java est un langage conçu pour élargir la base des développeurs tout en garantissant une qualité du développement. Ça a des avantages, ça a des inconvénient.

                              • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

                                Posté par (page perso) . Évalué à 3.

                                Ce que tu ne veux pas comprendre, c'est que la signature throw() indique que la fonction sur laquelle elle s'applique ne lancera jamais une exception.

                                Et ça c'est l'exemple du livre, de fonction qui ne lance jamais d'exception, j'ai bon?

                                void plop() throw() {
                                   throw std::exception();
                                }
                                
                                
      • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

        Posté par (page perso) . Évalué à 3.

        en C++, on se tape des arbres super-complexes de const à gérer ; modifier le status "const" d'une variable est quasiment impossible dans un programme complexe, le compilo hurle avec des milliers de messages d'erreur

        Je ne comprend pas vraiment où tu veux en venir. Le compilateur ne peut pas deviner que tu veux utiliser const, je ne vois donc pas de solution, à part ne pas l'utilisé, mais c'est aussi possible.

        « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

        • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

          Posté par . Évalué à 1.

          Je ne comprend pas vraiment où tu veux en venir. Le compilateur ne peut pas deviner que tu veux utiliser const, je ne vois donc pas de solution, à part ne pas l'utilisé, mais c'est aussi possible.

          Tu dis que c'est difficile ou que c'est impossible? Il me semble que

          double square(double x) {return x*x;}

          peut être sagement tagguée "const" par le compilo, qui peut décider quels appels de fonction sont const et lesquels ne le sont pas. Après, j'ai l'impression que la philosophie de D est de mettre le curseur à peu près à mi-chemin entre le compilo et le programmeur, le compilo peut deviner quelques trucs, mais l'aide du programmeur est indispensable à l'optimisation poussée, en explicitant la structure du programme : telle partie ne change pas, cette fonction ne peut pas lancer d'exceptions, etc. Je ne vois pas dans quelle mesure c'est fondamentalement différent de ce qui se passe en C ou en C++, par exemple.

          • [^] # Re: Y'a-t-il encore besoin de nouveaux langages "bas niveau"?

            Posté par (page perso) . Évalué à 7.

            Sauf que l'intérêt du const, c'est qu'il garanti que ça restera const même si tu change le corps de la fonction. Le cas que tu donne, c'est évident que le compilateur peut le deviner (d'ailleurs, une manière bête d'y arriver est d'ajouter const, voir si ça passe et sinon le retirer). Mais ajouter const fixe les évolutions de la fonction et c'est tout l'intérêt.

            « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

  • # cross compilation

    Posté par (page perso) . Évalué à 4.

    Une des raisons que me fait préférer les langages interprétés ou bytecodés, c'est la facilité de déploiement. Est-ce que les outils pour D propose une cross compilation facile afin de fournir facilement des binaires pour plein d'OS?

    http://devnewton.bci.im

    • [^] # Re: cross compilation

      Posté par (page perso) . Évalué à 2. Dernière modification le 11/06/12 à 18:19.

      Tout d'abord dans 90% des cas, si ce n'est plus, tu n'as pas a t'occuper du système d'exploitation car la bibliothèque standard s'en occupe pour toi. Si toutefois tu as ce besoin il y a la compilation conditionnelle. Bref exemple:

      import std.stdio;
      
      void main(){
          version(Windows){
              ....// code pour windows
          }
          version(Linux){
              ....// code pour linux
          }
          else{
              ....// code pour autres cas
          }
      
      }
      
      
  • # void et les templates?

    Posté par (page perso) . Évalué à 3.

    Parmi les 1001 aspects du C++ qui sont très pénibles quand on programme avec, il y a notamment le fait que:

    1. void est un type incomplet, en particulier on ne peut pas écrire void x pour déclarer un argument de type void à une fonction;
    2. les pointeurs vers fonction membre ne peuvent assignés aux pointeurs vers fonctions membres constantes(!);
    3. l'algèbre des types est difficile à manipuler parceque si on connaît le type pointeur vers fonction on ne peut pas en déduire le type pointeur vers fonction constante simplement.

    Ces points sont incroyablement agaçants lorsqu'on fait de la programmation générique. Qu'en est-il en D?

    Spécification de surcharge de méthode avec override

    Je pense que tu t'es mal exprimé, surcharge (polysémie) et redéfinition, ce n'est pas du tout la même chose!

    • [^] # Re: void et les templates?

      Posté par . Évalué à 2.

      void est un type incomplet, en particulier on ne peut pas écrire void x pour déclarer un argument de type void à une fonction;

      Mmmh, c'est pour bricoler des trucs avec des templates? Parce que je ne vois pas trop ce que tu peux faire du x, la variable n'a aucun sens, si?

      • [^] # Re: void et les templates?

        Posté par (page perso) . Évalué à 4.

        Mmmh, c'est pour bricoler des trucs avec des templates? Parce que je ne vois pas trop ce que tu peux faire du x, la variable n'a aucun sens, si?

        La variable n'a aucun sens dans le cas de void, mais dans les autres cas si, donc justement cela induit une exception dans le système des types qui est tout à fait nuisible à la programmation générique.

        Par exemple, essayons de définir un slot qui contient une fonction et une valeur sur laquelle appeler la fonction.

        template <T, P>
        class slot
        {
          public:
            typedef T take;
            typedef P pass;
            typedef T (*callback)(P);
        
            slot (callback _f, pass _x): f(_f), x(_x) {};
        
            T operator()() { return f(x); }
          private:
            callback f;
            pass x;
        };
        
        int
        f1(int x)
        {
           return x;
        }
        
        void
        f2()
        {}
        
        slot<int,int> c1(&f1);
        slot<void,void> c2(&f2);
        
        

        La première utilisation slot<int,int> fonctionne tandis que slot<void,void> explose!

        L'exemple de la définition de slot est très instructif parceque si on essaie d'en faire une solution robuste et générale, il faut:
        — utiliser des types proxies (des templates dont le seul rôle est de définir des types) parcequ'on passe les int, les pointeurs et les références par valeur mais les valeurs de la plupart des autres types par référence;
        ­— utiliser des call proxies pour encapsuler les appels à f(x) (à cause du void);
        ­— utiliser des constructeurs divers et variés parcequ'on a bien envie de pouvoir passer des pointeurs vers membres dans nos slots.

        Au final on arrive à un code très long et pas très lisible, pour faire correctement ce qui dans le cas général prend 6 lignes.

        • [^] # Re: void et les templates?

          Posté par (page perso) . Évalué à 1. Dernière modification le 13/06/12 à 02:12.

          dans ton exemple il me semble que tu as oublier de donner le second paramètre au constructeur de slot pour le premier c'est facile quand au second j'attends que tu complète j'imagine une fonction ?

          En attendant voila un début en D

          import std.stdio;
          
          struct slot(T,P) {
            public:
              alias T take;
              alias P pass;
              alias T function(P) callback;
          
              this (callback _f, pass _x){
                  f = _f;
                  x = _x;
              }
          
              T opCall() { return f(x); }
            private:
              callback f;
              pass x;
          };
          
          int f1(int x) {
             return x;
          }
          
          void f2() {}
          
          void main(){
              auto c1 = slot!(int , int)(&f1, 5);
              writeln( c1() );
          }
          
          
          ldc2 slot.d
          $ ./slot 
          5
          
          
          • [^] # Re: void et les templates?

            Posté par (page perso) . Évalué à 2.

            Tu as raison, c'est facile pour le premier, mais impossible à faire en C++ car il n'existe pas de valeur de type void. La question qui m'intéresse — par curiosité ­— est si le langage D répare cette defiscience de C++.
            c++
            slot<int,int> c1(&f1,0);
            slot<void,void> c2(&f2,/* valeur de type void */);

            La méthode classique pour s'en tirer consiste à utiliser les spécialisations de templates.

            • [^] # Re: void et les templates?

              Posté par (page perso) . Évalué à 1. Dernière modification le 13/06/12 à 12:11.

              je crois pas que tu puisse faire ça directement:

               auto c2 = new lot!(void, void )(&f2, cast(void)5);
              
              

              car ceci n'est pas autorisé:

              void x;
              
              

              void est utilisé seulement les types de retour de fonction.

              si x est une fonction alors c'est:

              void function() x
              
              

              maintenant si P est une fonction de type type void dans ce cas c'est possible. En D il y a quelque truc en plus par rapport au C++ alors peut être que ceci pourrait convenir: fonction et closures.

              • [^] # Re: void et les templates?

                Posté par (page perso) . Évalué à 2.

                Effectivement les closure font le job… ceci-dit c'est un peu dommage que les concepteurs du D — qui visiblement se sont un peu inspirés du C et du C++ — n'aient pas choisi de supprimer le type void pour le remplacer 1. par un type singleton (unit pour ceux qui parlent l'OCaml) un type qui n'a qu'une seule valeur, ce qui sert d'argument aux fonctions qui n'ont pas d'argument et de retour aux fonctions sans valeur de retour; et 2. par un type pointer qui remplacerait void* (il n'y a aucun rapport entre void et void* en C ou en C++).

                Au passage cela aurait été bien de décider entre pointeurs et références, cela ne sert à rien de garder les deux (à part à faire ch*er les programmeurs) ­— je n'ai pas vérifié en détail mais on dirait que D utilsie les deux.

                • [^] # Re: void et les templates?

                  Posté par (page perso) . Évalué à 2.

                  les pointeurs existe en D pour permettre d'interfacer avec du code C principalement. Ainsi il est assez rapide de faire une interface d'une bibliothèque C en D. Par exemple j'ai fait une interface pour x11 et fastcgi en quelques jour.

          • [^] # Re: void et les templates?

            Posté par . Évalué à 2.

            Pour le plaisir, l'équivalent OCaml:

            let slot f x = fun () -> f x
            
            let f1 x = print_endline "f1 called"; x
            let f2 () = print_endline "f2 called"
            
            let c1, c2 = slot f1 5, slot f2 ()
            
            let () =
              let x = c1 () in
              Printf.printf "result: %d\n" x;
              c2 ()
            
            
    • [^] # Re: void et les templates?

      Posté par (page perso) . Évalué à 1.

      Quel serait le sens d'une variable de type void ?

  • # linuxFR

    Posté par . Évalué à 2.

    Je ne sais pas mais moi dans l'addresse du site je vois fr hors chaque lien vers wikipédia pour définir la programmation orientée objet etc est en anglais…

    Si les versions francophones sont mauvaises je vous invite à les retravailler plutôt que nous emmener vers des pages en anglais.

    Mode chieur OFF.

    • [^] # Re: linuxFR

      Posté par (page perso) . Évalué à 3.

      Si les versions francophones sont mauvaises je vous invite à les retravailler plutôt que nous emmener vers des pages en anglais.

      Tu peux aussi t'y mettre. Mais personnellement, je n'ai pas envie de voir mon travail annulé parce qu'il manque des référence pour chaque mot écrit, du coup, je préfère faire des trucs plus productifs.

      « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

  • # import sélectif

    Posté par (page perso) . Évalué à 2.

    Quel est l'intérêt de l'import sélectif ?
    Le compilo n'inclus dans le binaire que les fonctions appelées, donc je vois pas bien ce qu'on gagne à pas inclure toute la lib.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.