IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Débats sur le développement - Le Best Of Discussion :

Conception et réalisation de programmes hautes performances et/ou sûrs


Sujet :

Débats sur le développement - Le Best Of

  1. #61
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut




    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques
      0  0

  2. #62
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par Nebulix Voir le message
    Ce débat sur "foreach" me semble bien illustrer le fait que les éditeurs utilisent pour vendre leurs "améliorations" des arguments du type " Vous n'aurez plus besoin de réfléchir à ..." ( aux limites des tableaux )
    Ca part de la constatation qui me semble être peu contestable que le cerveau du programmeur n'a pas une puissance de calcul infinie, et que la sémantique (le sens) d'un ptit foreach est beaucoup plus directement limpide que celui d'une boucle de 0 à la taille du tableau moins un et de l'affectation du contenu correspondant du tableau dans une variable locale. Ca permet d'exprimer dans le code le sens de ce que l'on veut faire sans avoir le nez dans le guidon à se concentrer exclusivement sur "comment" on veut le faire. Dit autrement, ça permet de prendre un peu de hauteur, ça rend le code plus clair, concis et lisible. Le programmeur y gagne parce qu'il a moins à écrire et à plus confiance dans son code. Les relecteurs éventuels y gagnent parce que le code est plus clair. Qui y perd quoi que ce soit ?

    Citation Envoyé par Nebulix Voir le message
    1) Il y a des cas où il aurait mieux valu réfléchir car retrouver le bug fait perdre beaucoup plus de temps
    En quoi une boucle foreach introduit des bugs qu'il n'y aurait pas dans une boucle for ???
    Citation Envoyé par Nebulix Voir le message
    2) Ces arguments ont beaucoup de succès entrainant une inflation de la complexité des logiciels au détriment de leur qualité et surtout de leur pérennité.
    En quoi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int sum = 0;
    foreach(e : t)
      sum += e;
    fait une "inflation de la complexité des logiciel" par rapport à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int sum = 0;
    int n = t.size();
    for(int i = 0; i < n; ++i)
      sum += t[i];
    ??

    Citation Envoyé par Nebulix Voir le message
    Utilisant des variables statiques avec Delphi, je n'ai jamais eu de problème de mémoire.
    "Vu que je pré-alloue tout, j'ai jamais de problème avec l'allocation".
    Super...

    Citation Envoyé par Nebulix Voir le message
    Réfléchir à ce qu'il faut contrôler soi-même et ce qu'on peut déléguer ( ici à des boîtes noires ) est aussi important en informatique qu'ailleurs.
    Elle est où la boite noire ?? C'est un foreach. Le sens en est parfaitement clair !
    Et puis pourquoi tu utilises des boucles for, et tu ne te limites pas uniquement à des boucle while ? C'est vachement plus mieux quand même ! Au moins on ne délègue pas...
      0  0

  3. #63
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    Ca part de la constatation qui me semble être peu contestable que le cerveau du programmeur n'a pas une puissance de calcul infinie, et que la sémantique (le sens) d'un ptit foreach est beaucoup plus directement limpide que celui d'une boucle de 0 à la taille du tableau moins un et de l'affectation du contenu correspondant du tableau dans une variable locale.
    Tu n'oublieras pas juste avant la boucle le commentaire "// On parcourt tous les éléments du tableau."

    On ne sait jamais, hein, d'ici à ce que l'on tombe sur des développeurs qui ne savent pas non plus lire du code...

    Il n'y a pas de problèmes de "compréhension" d'une boucle "for" par rapport à "foreach", c'est plutôt un problème de parcours parfois complexe (certaines collections / maps par exemple) et de feignantise et/ou d'ignorance des limites des éléments parcourus.

    Si un développeur n'arrive pas à comprendre une simple boucle "for" et/ou mets des commentaires qui reprennent en français le code ("on affecte X à Y", "on retourne la valeur", etc.), faut plutôt s'inquiéter de lui laisser toucher du code critique, que ce soit au niveau performances ou au niveau sûreté... Cf. titre du sujet, pour rappel.

    Citation Envoyé par alex_pi Voir le message
    En quoi une boucle foreach introduit des bugs qu'il n'y aurait pas dans une boucle for ???
    Déjà eu le cas sur des tableaux associatifs, les éléments non vectorisés étaient parcourus eux aussi en plus de la partie vecteur...


    En l'occurrence, il y a manifestement un problème de traduction du "foreach" au niveau performances (peut-être corrigé depuis, je ne suis pas spécialement ça non plus). Il peut y avoir des effets de bord. Et un développeur est censé savoir lire du code, et mettre des commentaires judicieux dans ce dernier afin d'expliquer les concepts et les actions et non pas les détails d'implémentation redondants avec le code lui-même.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO
      0  0

  4. #64
    alex_pi
    Invité(e)
    Par défaut
    On ne dit pas qu'il faut supprimer la boucle for, arrête de craquer. Juste que la boucle foreach est un gain de clarté quand on fait quelque chose pour chaque élément d'un conteneur.
      0  0

  5. #65
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    On ne dit pas qu'il faut supprimer la boucle for, arrête de craquer. Juste que la boucle foreach est un gain de clarté quand on fait quelque chose pour chaque élément d'un conteneur.
    Et c'est justement là le problème : sur des conteneurs complexes, le "pour chaque" risque de poser un sacré souci... En incluant des choses qui ne devraient pas forcément en faire partie.

    Pour ma part, j'ai tendance à n'utiliser de syntaxes genre "foreach" qu'en initialisation / finalisation, de manière à être certain de ne rien oublier. En traitement, je préfère expliciter les intervalles de traitement.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO
      0  0

  6. #66
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Et c'est justement là le problème : sur des conteneurs complexes, le "pour chaque" risque de poser un sacré souci...
    C'est justement là que le foreach est intéressant, puisqu'il se base sur l'itérateur qui a été spécialement défini pour le type de conteneur sur lequel tu te trouves. Si c'est compliqué, tu définis une fois comment se fait un parcours sur ta structure, et après tu restes sur ce parcours. C'est donc bien dans les cas où la structure est compliquée que le foreach est un énorme gain.
      0  0

  7. #67
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par _skip Voir le message
    Si tu travailles sur un intervalle bien défini, c'est sûr que for est plus adapté.
    Le léger overhead du "foreach" suggèrerait plutôt que le "for" est toujours plus adapté...

    Ceci étant dit, l'intérêt primaire du for (au niveau source) est, justement, d'expliciter les bornes. Retrouver un débordement de tableau masqué par un "foreach" n'est pas toujours simple, alors que c'est trivial avec un "for".

    C'est le cas que j'ai eu avec des tableaux associatifs, que j'ai indiqué un peu plus haut : la partie "map" du tableau a été parcourue en même temps que la partie "vecteur" via le "foreach", alors que la map aurait été correctement ignorée avec un "for".
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO
      0  0

  8. #68
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    C'est donc bien dans les cas où la structure est compliquée que le foreach est un énorme gain.
    Non. Redéfinition d'opérateur, tu le spécialise comme ça te fait envie ensuite.

    Prends justement le cas d'un conteneur mixte map / vector (tableau associatif, donc), et regarde donc les conséquences (lourdes) qu'il peut y avoir à tout parcourir...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO
      0  0

  9. #69
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Ceci étant dit, l'intérêt primaire du for (au niveau source) est, justement, d'expliciter les bornes. Retrouver un débordement de tableau masqué par un "foreach" n'est pas toujours simple, alors que c'est trivial avec un "for".
    Ce qui fait qu'il n'est pas simple de retrouver le débordement de tableau dans un foreach, c'est justement qu'il n'y en a pas...

    Citation Envoyé par Mac LAK Voir le message
    C'est le cas que j'ai eu avec des tableaux associatifs, que j'ai indiqué un peu plus haut : la partie "map" du tableau a été parcourue en même temps que la partie "vecteur" via le "foreach", alors que la map aurait été correctement ignorée avec un "for".
    En même temps, si tu ne veux pas accéder à tous les éléments, c'est sûr que dire "pour tout élément", c'est un peu débile non ?

    Citation Envoyé par Mac LAK Voir le message
    Non. Redéfinition d'opérateur, tu le spécialise comme ça te fait envie ensuite.
    Quel opérateur ? Les méthodes d'itération ? C'est bien ça qu'on fait pour avoir un itérable sur lequel on peut appeler un foreach...
      0  0

  10. #70
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    Ce qui fait qu'il n'est pas simple de retrouver le débordement de tableau dans un foreach, c'est justement qu'il n'y en a pas...
    Débordement logique : itérer sur des valeurs qu'il n'était pas souhaitable d'itérer.

    Citation Envoyé par alex_pi Voir le message
    En même temps, si tu ne veux pas accéder à tous les éléments, c'est sûr que dire "pour tout élément", c'est ptet un peu débile non ?
    Sauf lorsque tu présupposes que tu veux accéder à "tous les éléments" alors que tu n'as pas forcément le contrôle du contenu... Et que des scories peuvent traîner.

    Je te le répète : prends le cas d'un conteneur mixte map / vector... Et trouves-moi donc un "++" qui gère les deux en fonction du contexte, sans risque de confusion. Ce genre de structure est fréquente dans les langages de script notamment (Javascript, PHP, LUA, Python, etc...), ce qui peut poser des problèmes assez mignons quand tu t'interfaces avec eux.

    Pendant ce temps, je ferais un "for", j'irais vingt fois plus vite, et il n'y aura pas de risque d'erreurs quel que soit la configuration du conteneur : vecteur "pur" (for=foreach, donc), map "pure" (=vide pour le "for"), ou mixte.

    Citation Envoyé par alex_pi Voir le message
    Quel opérateur ? Les méthodes d'itération ? C'est bien ça qu'on fait pour avoir un itérable sur lequel on peut appeler un foreach...
    Ou un "++" dans un "for". Cela revient exactement au même, quand on sait lire du code.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO
      0  0

  11. #71
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Débordement logique : itérer sur des valeurs qu'il n'était pas souhaitable d'itérer.
    Le très fameux "débordement de tableau" logique...

    Citation Envoyé par Mac LAK Voir le message
    Sauf lorsque tu présupposes que tu veux accéder à "tous les éléments" alors que tu n'as pas forcément le contrôle du contenu... Et que des scories peuvent traîner.
    Oui j'avoue, quand je préconise d'utiliser un foreach, c'est que je présuppose que c'est pour tout élément.. Et dans ton exemple récurent, ou que tu expliques que tu ne sais pas ce qu'il y a dans ton tableau, comment tu vas le parcourir avec une boucle for de toutes façons ?
      0  0

  12. #72
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    Oui j'avoue, quand je préconise d'utiliser un foreach, c'est que je présuppose que c'est pour tout élément.. Et dans ton exemple récurent, ou que tu expliques que tu ne sais pas ce qu'il y a dans ton tableau, comment tu vas le parcourir avec une boucle for de toutes façons ?
    Sur sa partie vectorielle.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO
      0  0

  13. #73
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    A quel moment j'ai dit qu'il ne fallait plus faire de boucle for ? Ah oui, je me souviens : JAMAIS. Par contre, quand tu peux faire un foreach, oui, j'insiste, c'est plus clair, c'est mieux..
    Non, ce serait plutôt ton état d'esprit général que je visais en l'occurrence.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO
      0  0

  14. #74
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    C'est justement là que le foreach est intéressant, puisqu'il se base sur l'itérateur qui a été spécialement défini pour le type de conteneur sur lequel tu te trouves. Si c'est compliqué, tu définis une fois comment se fait un parcours sur ta structure, et après tu restes sur ce parcours. C'est donc bien dans les cas où la structure est compliquée que le foreach est un énorme gain.

    je tiens à rappeler 2 points :
    1. nous sommes dans une discussion où le programme lambda n'est pas un exemple acceptable... on s'est placé dans un cadre avec performances et/ou sûreté très élevée(s), donc :
      • si les performances sont cruciales, le léger surcoût du foreach est peut-être à éviter... après rien ne dit que statiquement, on ne puisse pas "émuler" cette fonctionnalité à moindre coût en repassant sur le for approprié sur le code qui sera réellement compilé (bien sûr cette introduction à la main sera faite dans les cas où l'on sait que la réécriture automatique fonctionnera). sinon, a priori on s'en passera
      • si la sûreté est le seul critère, merci de comparer l'analyse qu'il est possible de faire sur un foreach et sur un for (vérification formelle, calcul d'invariant à la main, etc)
    2. en ce qui concerne les itérateurs, sachez que des experts C++ comme Alexandrescu considèrent qu'ils devraient disparaître au profit des ranges
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog
      0  0

  15. #75
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par gorgonite Voir le message
    si les performances sont cruciales, le léger surcoût du foreach est peut-être à éviter... après rien ne dit que statiquement, on ne puisse pas "émuler" cette fonctionnalité à moindre coût en repassant sur le for approprié sur le code qui sera réellement compilé (bien sûr cette introduction à la main sera faite dans les cas où l'on sait que la réécriture automatique fonctionnera). sinon, a priori on s'en passera
    Sur le cas du parcours complet de tableau par exemple, il apparaît trivial de rétablir le niveau de performance d'un for(), si ce n'était pas le cas dans une version de .Net, je suspecte que ce ne l'est plus maintenant et il n'y a aucune raison fondamentale que cette disparité existe. Dans le cas d'un itérateur, je ne vois aucune raison pour que la boucle for() amène un surcroit de performance.
    Dans les autres emplois de for()... Je ne vois pas pourquoi on utiliserait un foreach() pour ces cas.

    En bref, foreach() ou for() sont a priori équivalent en performances lorsqu'ils peuvent être utilisés tous deux raisonnablement, il faut juger les performances implémentation par implémentation et prendre ses décisions en fonction du rapport "pénalité en performance/amélioration de la lisibilité" (critère subjectif, et propre au domaine). Si foreach() et for() sont équivalents comme ils devraient l'être, je ne vois pas de raison de préférer for() à foreach() comme je vais m'en expliquer maintenant :

    Citation Envoyé par gorgonite Voir le message
    si la sûreté est le seul critère, merci de comparer l'analyse qu'il est possible de faire sur un foreach et sur un for (vérification formelle, calcul d'invariant à la main, etc)
    L'avantage du foreach() c'est qu'il fait exactement ce qu'on lui demande (parcourir intégralement un conteneur/itérateur) de façon immédiatement lisible. Donc en assumant que l'itérateur soit écrit correctement, on est garanti de bien le parcourir (je fais ici abstraction des problèmes des conteneurs mutable en présence de threads, le problème est le même pour for ou foreach, encore que foreach pourrait locker automatiquement le conteneur dans une implémentation hypothétique). Un for() écrit dans ce but peut contenir des erreurs à plusieurs points (affectation, test de fin, next) et n'apporte aucune garantie supplémentaire.
    Il suffit de vérifier la correction de l'itérateur pour être assuré de la correction de tous les foreach l'utilisant alors que pour être certain de la correction de tous ces parcours, il faudrait vérifier chaque for() employant cet itérateur de façon ad-hoc.

    Pour un tableau, le problème est encore plus flagrant : il est aisé de faire des erreurs de bornes dans un for() (je n'en fait qu'extrêmement peu et je ne doute pas que MacLak ou Souviron n'en fasse encore moins mais la perfection n'est pas de ce monde) alors qu'un foreach() ne faillira jamais à sa tâche si l'implémentation de sa compilation est correcte (et il est peu probable qu'elle ne le soit pas sans que cela soit détecté très vite, encore qu'apparemment on n'aie pas les même garanties sur ses performances).

    Je répète encore une fois que mon argumentation ci-dessus n'est valable que pour les cas où l'emploi de foreach() est possible sans contorsion, for() est plus flexible et doit être l'outil de choix pour parcourir une partie d'un conteneur ou autre tâche non-réalisable par foreach(), celui-ci doit être réservé au parcours intégral de conteneur/itérateur.

    Citation Envoyé par gorgonite Voir le message
    en ce qui concerne les itérateurs, sachez que des experts C++ comme Alexandrescu considèrent qu'ils devraient disparaître au profit des ranges
    Tu emploies ici des termes techniques propres au C++, les ranges seraient sans doute considéré comme des "itérateurs" dans un autre langage, même s'ils viennent corriger un défaut des itérateurs employées en C++ jusqu'ici.

    --
    Jedaï
      0  0

  16. #76
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par Jedai Voir le message
    Tu emploies ici des termes techniques propres au C++, les ranges seraient sans doute considéré comme des "itérateurs" dans un autre langage, même s'ils viennent corriger un défaut des itérateurs employées en C++ jusqu'ici.
    j'emploie le terme itérateur au sens POO, et aucune confusion n'est possible puisque je mets un exemple (d'ailleurs ce n'est pas spécifique au C++, ça marche aussi en Java, D... sous des formes différentes, mais avec les mêmes idées de base)

    "corriger un défaut" n'est pas le terme exact, je dirais juste qu'ils permettent d'obtenir une abstraction plus dissociée de la notion de pointeur que les itérateurs de la POO devaient abstraire à l'origine
    mais à quel prix ? je suis encore dubitatif (surtout quand on voit un exemple racontant qu'il est impossible de faire un itérateur sur un arbre )
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog
      0  0

  17. #77
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par gorgonite Voir le message
    j'emploie le terme itérateur au sens POO, et aucune confusion n'est possible puisque je mets un exemple
    Quel exemple ? Par ailleurs à propos des ranges, je n'ai rien trouvé de particulièrement concluant avec une recherche superficielle excepté qu'elles insistaient sur des conteneurs ordonnés et qu'elle permettaient de prendre une "tranche" d'un tel conteneur. Tu aurais des liens plus précis à nous proposer et une explication d'en quoi elle ne sont pas des itérateurs ?

    --
    Jedaï
      0  0

  18. #78
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par gorgonite Voir le message
    en ce qui concerne les itérateurs, sachez que des experts C++ comme Alexandrescu considèrent qu'ils devraient disparaître au profit des ranges
    Tiens, un vieux concept revenant au goût du jour... Point fort du Pascal et de l'Ada, ça, les intervalles.

    Citation Envoyé par Jedai Voir le message
    je suspecte que ce ne l'est plus maintenant et il n'y a aucune raison fondamentale que cette disparité existe.
    Ce qui demande une preuve : soit un KB Microsoft décrivant la correction, soit une série de benchs montrant que le "foreach" est désormais traduit à l'identique d'un "for" quel que soit le cas d'utilisation.

    Citation Envoyé par Jedai Voir le message
    Dans le cas d'un itérateur, je ne vois aucune raison pour que la boucle for() amène un surcroit de performance.
    C'est pourtant le cas, d'après le bench effectué... Ce n'est pas parce que conceptuellement, c'est "presque" la même chose que ça l'est réellement une fois traduit en code machine. Cela peut être lié à une variante d'inlining, à une passe différente d'optimisation, à un séquencement légèrement différent de la traduction, ou encore à une occupation plus importante des registres avec le "foreach", obligeant alors à utiliser un peu plus la pile (qui est plus lente qu'un registre).
    Bref, des raisons pour cette disparité, il y en a plein, toutes aussi valables les unes que les autres. Cela ne justifie pas le fait que la traduction ne soit pas identique pour un parcours identique, bien sûr, mais cela explique pour quelles raisons il peut y avoir une différence.

    Citation Envoyé par Jedai Voir le message
    L'avantage du foreach() c'est qu'il fait exactement ce qu'on lui demande (parcourir intégralement un conteneur/itérateur) de façon immédiatement lisible.
    Encore faut-il que cela soit vrai... Prenons le cas d'un tableau dynamique, qui serait rempli par un autre thread suivant un algo FIFO (= en fin de tableau).

    Si ta boucle est effectuée via un "foreach", que se passe-t'il ? Entre-t'on en boucle infinie si la production est supérieure en vitesse à la consommation, pour cause d'itérateur "end()" jamais atteint ? Si oui, c'est un problème.
    S'arrête-t'on avant, car le "end()" a été évalué précédemment ? Si oui, c'est un plus gros problème encore, car le "foreach" viole alors sa postcondition (traiter TOUS les éléments).

    Via un "for", tu récupères à un instant T le nombre d'éléments du tableau (donc "tous" en début de boucle), puis tu les consommes, quel que soit le nombre d'éléments ajoutés au tableau pendant la consommation. Ton algorithme s'arrête, pas de boucle infinie, les contextes d'exécution multitâche ne sont pas bloqués et tout va bien.

    C'est ça, la supériorité de décider soi-même de ce que l'on fait, au lieu de laisser la machine décider à ta place. C'est la même chose qu'avec les casts implicites : c'est mal, si cast il doit y avoir, alors c'est au programmeur de décider lequel... Ne serait-ce que pour assurer un fonctionnement constant, notamment en cas de changement d'implémentation de l'implicite ou de portage.

    Citation Envoyé par Jedai Voir le message
    Il suffit de vérifier la correction de l'itérateur pour être assuré de la correction de tous les foreach l'utilisant alors que pour être certain de la correction de tous ces parcours, il faudrait vérifier chaque for() employant cet itérateur de façon ad-hoc.
    L'itérateur est le même pour "foreach" et "for" : s'il est buggé, il plantera pareil pour l'un ou pour l'autre. Ou ta boucle "for" ne bouclera carrément pas du tout si tu oublie d'itérer, ce qui est quand même un bug plutôt visible (et surtout, un bug d'ultra débutant...).

    Citation Envoyé par Jedai Voir le message
    for() est plus flexible et doit être l'outil de choix pour parcourir une partie d'un conteneur ou autre tâche non-réalisable par foreach(), celui-ci doit être réservé au parcours intégral de conteneur/itérateur.
    Tu viens justement de citer le maître-mot : flexibilité. Ou, pour utiliser un synonyme adapté au contexte, déterminisme de fonctionnement. Le "for", on le contrôle de A à Z, le "foreach", non.

    C'est pour cette raison que je n'utilise pas de "foreach" en dehors des initialisations / finalisations, c'est à dire dans un état particulier de l'application où les interactions entre threads, processus et machines n'existent pas encore... Cas très limité s'il en est, car cela revient à dire que l'on fait un programme monothread, ne communiquant pas, n'interagissant pas avec l'utilisateur, ni avec les autres processus... Un "Hello world" ou peu s'en faut, donc, dans tous les cas quelque chose de potentiellement peu complexe et/ou peu utile...

    Dans ce cas précis, il permet d'effectuer un traitement sur tous les éléments sans en oublier (mais aucun ne peut être ajouté / retiré pendant l'itération non plus, hein...), et ne demande pas de modifier le code en cas d'ajout ou suppression d'un élément.

    Dans tous les autres cas, du moment que le cardinal du conteneur peut évoluer, c'est une plaie potentielle... Et un lock serait trop coûteux en temps CPU, alors que ce serait la seule solution pour le rendre "fiable". Dans le même temps, un "for" permet d'obtenir quelque chose de sécurisé et fiable sans utiliser le moindre lock... Donc, plus performant, plus sûr, que des avantages, quoi...

    Tu penses que le "foreach" est supérieur sur un parcours complet parce que tu n'as manifestement pas l'habitude de déterminer l'environnement d'une fonction impérative, ni les impacts potentiels d'un parcours rendu rigide au point d'être néfaste. Programmer en impératif, cela ne se fait pas avec des concepts et un raisonnement fonctionnels.

    Citation Envoyé par Jedai Voir le message
    Tu emploies ici des termes techniques propres au C++, les ranges seraient sans doute considéré comme des "itérateurs" dans un autre langage, même s'ils viennent corriger un défaut des itérateurs employées en C++ jusqu'ici.
    Pas tout à fait... Un range, en Pascal ou Ada, est quelque chose qui est soit figé par compilation (domaine de validité d'un type, par exemple, ou bornes d'un tableau statique), soit déterminé à la compilation (bornes d'un tableau dynamique notamment).

    Dans les deux cas, itérer dessus se fait de façon particulière, propre à ce concept, et est considéré comme "la bonne manière" d'itérer sur une plage.
    Cela marche notamment pour les ensembles et les énumérations, qui, je le rappelle, n'ont pas de valeur autre que symbolique dans ces deux langages. L'autre manière de les utiliser est l'usage de "Pred" et "Succ", qui seraient implémentés en C++ par surcharge de "++" et "--" respectivement. Sauf qu'en Pascal et Ada, la surcharge en question n'est ni nécessaire, ni souhaitable : c'est la déclaration de l'ensemble (ou de l'énumération) qui définit l'ordre algébrique des éléments, ainsi que le premier et le dernier, et ceci au moment de la compilation et de l'exécution pour les dépassements d'intervalles.

    Citation Envoyé par gorgonite Voir le message
    mais à quel prix ? je suis encore dubitatif (surtout quand on voit un exemple racontant qu'il est impossible de faire un itérateur sur un arbre )
    Ce qui est tout à fait logique, car un arbre peut posséder deux successeurs ou plus, et non pas un seul... Ce qui empêche totalement le concept de Ranges d'être appliqué.

    Les ranges s'appliquent sur tout conteneur, domaine, intervalle linéaire (ou unidimensionnel, au choix), qu'il contienne ou non des trous, tant qu'il est possible de définir une sorte de "groupe" (au sens mathématique du terme) dessus.

    L'avantage qu'ils ont par rapport aux itérateurs, c'est qu'une grande partie du contrôle peut être faite au niveau de la compilation, et non pas uniquement à l'exécution. En dehors de ça, ils peuvent bien entendu s'appliquer à tout ou partie de l'objet ciblé, y compris par accès direct contrairement à certains itérateurs "purs" qui fonctionnent exclusivement par parcours séquentiel depuis le début du conteneur.

    Donc, en résumé, un range est supérieur à un itérateur parce que :
    • Il est résolu en partie à la compilation, parfois même totalement.
    • Il permet un accès direct [aléatoire] aux éléments internes, et ne requiert pas de parcours systématique grâce à la résolution partielle au niveau compilation.


    Leur inconvénient majeur : impossibilité stricte d'avoir plus d'un successeur, et plus d'un prédécesseur. Ce qui rend effectivement impossible leur utilisation pour un arbre (mais ce serait éventuellement possible sur une chaîne de l'arbre, bien que l'intérêt soit limité).
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO
      0  0

  19. #79
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    Mais pour autant que je sache, personne n'a dit que foreach devait dans tous les cas remplacer for. Juste que c'est une syntaxe agérable et confortable à lire lorsqu'on itère une collection ou un tableau en faisant une action spécifique avec chacun des éléments.

    Dans mes codes, ne devoir traiter qu'un intervalle plutôt que la totalité d'une collection, ça arrive plus rarement (je parle pour moi).

    Il faut savoir aussi que foreach fonctionne sur tous types de collections, ce qui inclut les bags, les queues, les sets, les maps et pas seulement les listes indexées. Rien qu'on peut pas faire avec un for() en étant prudent en cas de listes chaînées à ne pas refaire le parcours depuis le début à chaque itération.

    Via un "for", tu récupères à un instant T le nombre d'éléments du tableau (donc "tous" en début de boucle), puis tu les consommes, quel que soit le nombre d'éléments ajoutés au tableau pendant la consommation. Ton algorithme s'arrête, pas de boucle infinie, les contextes d'exécution multitâche ne sont pas bloqués et tout va bien.
    2 choses, est-ce que la majorité des scénarios de parcours itératifs se font dans des contextes de concurrences? Dans mon cas quotidien la réponse est clairement non.

    Pour ce qui est du parcours de X éléments d'une file d'attente par un thread consommateur à l'aide d'un for, tu n'as guère beaucoup de garantie si des éléments peuvent être enlevés de la listes des tâches derrière ton dos, soit par une action utilisateur, une modification prioritaire, ou un autre thread qui consomme la file.

    En gros il faudra une structure telle qu'une queue bloquante, et c'est des opérations du style push et pop individuelles qui seront utilisées et non des parcours.

    En fait, comparer for et foreach en les mettant dans des contextes ou ils ne sont clairement pas adaptés, ça vaut pas la peine.
      0  0

  20. #80
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Ce qui est tout à fait logique, car un arbre peut posséder deux successeurs ou plus, et non pas un seul... Ce qui empêche totalement le concept de Ranges d'être appliqué.

    je parlais d'un itérateur, pas d'un range... et en cachant un accumulateur dans ton itérateur, tu peux avoir un const_iterator sur un arbre quelconque.
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog
      0  0

Discussions similaires

  1. Réponses: 1
    Dernier message: 26/10/2012, 10h19
  2. réalise un programme avec Delphi tres compliqué
    Par ouldfella dans le forum Delphi
    Réponses: 11
    Dernier message: 04/09/2006, 23h49
  3. Réponses: 15
    Dernier message: 18/05/2006, 13h43
  4. conception et réalisation d'une application client/serveur
    Par masvivi dans le forum Développement
    Réponses: 1
    Dernier message: 24/08/2005, 12h32
  5. Qui a inventé le concept de "langage de programmation?
    Par Biane dans le forum Langages de programmation
    Réponses: 10
    Dernier message: 11/02/2004, 10h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo