Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 14 sur 14
  1. #1
    HRS
    HRS est déconnecté
    Membre expérimenté Avatar de HRS
    Inscrit en
    mars 2002
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 643
    Points : 576
    Points
    576

    Par défaut equivalent "continue" en C, "next" en PERL

    exit permet de sortir d'une boucle

    mais pour mettre fin à l'itération courante et aller directement à la suivante,

    n'y a t-il pas mieux en ADA qu'un "goto" ?

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    loop
    .
    .
    .
                  if condition then
                     goto next;
                  end if;   
    .
    .
    <<next>>null;
    end loop;

  2. #2
    Membre régulier Avatar de poincare
    Homme Profil pro Henri Poincare
    Architecte technique
    Inscrit en
    mai 2007
    Messages
    48
    Détails du profil
    Informations personnelles :
    Nom : Homme Henri Poincare
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : mai 2007
    Messages : 48
    Points : 75
    Points
    75

    Par défaut

    Il n'y a pratiquement jamais besoin d'un GOTO en Ada.
    Faire :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    loop
    .
    .
    .
         if not(condition) then
    
    
    
         end if;   
    end loop;

  3. #3
    HRS
    HRS est déconnecté
    Membre expérimenté Avatar de HRS
    Inscrit en
    mars 2002
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 643
    Points : 576
    Points
    576

    Par défaut

    par commodité, vous avez placé le "end if" devant le "end loop", mais prenons
    le cas suivant (les . en colonne 1 sont des instructions quelconques)

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    loop
    .
    .
    .
               if condition1 then
    .
    .           
    .
                  if condition2 then
                     goto next;
                  end if;
    .
    .                        
               end if;                 
    .
    .
    <<next>>null;
    end loop;

  4. #4
    Membre régulier
    Profil pro
    Mathématicien
    Inscrit en
    mars 2012
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Mathématicien
    Secteur : Finance

    Informations forums :
    Inscription : mars 2012
    Messages : 70
    Points : 97
    Points
    97

    Par défaut

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    loop
               ok:= True;
    .
               if condition1 then
    .
                  if condition2 then
                     ok:= False;
                  end if;
                  if ok then
    .
                  end if;
    .                        
               end if;                 
               if ok then
    .
               end if;
    .
    end loop;
    voire un appel d'une procédure avec des "return" là où tu mettrais des "continue"

  5. #5
    HRS
    HRS est déconnecté
    Membre expérimenté Avatar de HRS
    Inscrit en
    mars 2002
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 643
    Points : 576
    Points
    576

    Par défaut

    l'appel d'une procédure/fonction entre "loop end loop;" est en effet une
    solution

    par contre "if ok then" à plusieurs endroits du code, c'est pire que le "goto"

  6. #6
    Membre régulier Avatar de poincare
    Homme Profil pro Henri Poincare
    Architecte technique
    Inscrit en
    mai 2007
    Messages
    48
    Détails du profil
    Informations personnelles :
    Nom : Homme Henri Poincare
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : mai 2007
    Messages : 48
    Points : 75
    Points
    75

    Par défaut Jamais besoin de GOTO en Ada

    Rien ne vaut un exemple pour montrer qu'on peut traduire une boucle en C++ avec 2 <continue> en Ada sans aucun GOTO.
    Au début, on rale, mais après on constate que le code Ada est plus clair :

    Code C++ de départ :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
       for (; iPiece < N_PIECE_TYPE; iPiece++, pieceMask <<= 1)
       {
          // skip if we've already used this piece
          if (pieceMask & placedPieces)
             continue;
    
          placedPieces |= pieceMask;
    
          for (int iOrient = 0; iOrient < allowed.nPieces[iPiece]; iOrient++) {
             BitVec pieceVec = allowed.pieceVec[iPiece][iOrient];
    
             // check if piece conflicts with other pieces
             if ((pieceVec & boardVec) || hasBadIslands(boardVec | pieceVec, row))
                continue;
    
             m_curSoln.pushPiece(pieceVec, iPiece, row);
    
             // recur or record solution
             if (placedPieces != Piece::ALL_PIECE_MASK)
                genAllSolutions(boardVec | pieceVec, placedPieces, row);
             else
                recordSolution(m_curSoln);
    
             // remove the piece before continuing with a new piece
             m_curSoln.popPiece();
          }
    
          placedPieces ^= pieceMask;
       }
    Traduction en Ada (avec des ajouts):
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    loop
    
             -- go on only if we've not already used this piece
                if (Piecemask and l_placedPieces) = 0 then
                   l_placedPieces := l_placedPieces or Piecemask;
    
                   for Iorient in 0 .. Allowed.nPieces (ipiece) loop
                      piecevec := Allowed.pieceVec (ipiece, Iorient);
    
                      --check if piece conflicts with other pieces
                      if (piecevec and l_boardVec) = 0 then
                         -- add the piece to the board
                         l_boardVec := l_boardVec or piecevec;
                         if Has_Bad_Islands (l_boardVec, l_Row) = Good then
    
                            pushPiece (m_curSoln, piecevec, ipiece, l_Row);
                            -- recur or record solution
                            if (l_placedPieces /= ALL_PIECE_MASK) then
                               Gen_All_Solutions
                                 (l_boardVec,
                                  l_placedPieces,
                                  l_Row);
                            else
                               Record_Solution (m_curSoln);
                               popPiece (m_curSoln);
                               return;
                            end if;
                            if M_NSoln >= Max_NSoln then
                               return;
                            end if;
                            popPiece (m_curSoln);
                         end if;
                         -- remove the piece before continuing with a new piece
                         l_boardVec := l_boardVec xor piecevec;
                      end if;
                   end loop;
    
                   l_placedPieces := l_placedPieces xor Piecemask;
                end if;
                exit when ipiece = Piecenr'Last;
                ipiece    := ipiece + 1;
                Piecemask := Shift_Left (Piecemask, 1);
             end loop;

  7. #7
    Membre régulier
    Profil pro
    Mathématicien
    Inscrit en
    mars 2012
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Mathématicien
    Secteur : Finance

    Informations forums :
    Inscription : mars 2012
    Messages : 70
    Points : 97
    Points
    97

    Par défaut

    Probablement tout le monde est d'accord sur le fait qu'on n'a jamais besoin d'un "goto".

    Maintenant, l'absence d'un "continue" ou "next" peut AMHA entraîner des constructions qui alourdissent le code ou le sur-indentent, exactement de la même manière que si l'instruction "return" manquait pour sortir d'une procédure quand il n'y plus de bonne raison de continuer. J'ai quelques souvenirs de programmation Pascal où l'enjeu était d'arriver à "end" dans tous les cas et bien sûr sans devoir recourir à un "goto" (<- pouargh!)...

    J'ajoute "goto loop end" à ma liste de voeux pour Ada 2020 ;-) .
    Il faudrait juste éviter le mot-clé "goto" qui a une triste réputation...

    Juste encore une idée moche pour simuler "continue" ou "next":

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    loop
      essai: for bidon in 1..1 loop
    .
         exit essai when ça_foire_inutile_d_insister;
    .
      end loop essai;
    end loop;

  8. #8
    HRS
    HRS est déconnecté
    Membre expérimenté Avatar de HRS
    Inscrit en
    mars 2002
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 643
    Points : 576
    Points
    576

    Par défaut

    par provocation, je remplace le label "essai" par "continue"

    sinon cette solution n'est pas si moche que cela et me plait mieux que la
    procédure/fonction évoquée

    pour 2025, je demande

    Code :
    1
    2
    3
    4
    5
    6
    7
    loop
    
    .
         next when ça_foire_inutile_d_insister;
    .
    
    end loop;

  9. #9
    Nouveau Membre du Club
    Inscrit en
    octobre 2010
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : octobre 2010
    Messages : 21
    Points : 29
    Points
    29

    Par défaut

    Vu que ça n'a pas encore été proposé, je suggère le recours à une exception :

    Code Ada :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    next : exception; -- dans un block déclaratif
    [...]
    loop
      begin
        [...]
        if condition then
          raise next;
        end if;
        [...]
      exception
        when next => null;
        when others => raise;
      end;
    end loop;

  10. #10
    Membre régulier Avatar de poincare
    Homme Profil pro Henri Poincare
    Architecte technique
    Inscrit en
    mai 2007
    Messages
    48
    Détails du profil
    Informations personnelles :
    Nom : Homme Henri Poincare
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : mai 2007
    Messages : 48
    Points : 75
    Points
    75

    Par défaut

    L'exception répond bien à la question, il reste juste à vérifier qu'il n'y a pas de pénalité en temps d'execution : suivant l'"implémentation, le traitement d'exception peut être couteux.

  11. #11
    HRS
    HRS est déconnecté
    Membre expérimenté Avatar de HRS
    Inscrit en
    mars 2002
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 643
    Points : 576
    Points
    576

    Par défaut

    cela ne marche pas trop bien si à l'intérieur du loop, il y a des conditions qui entrainent "next", d'autres qui entrainent "exit" à un ou plusieurs niveaux

    en fin de compte, la boucle "une fois" de Zerte répond le mieux au problème

    Code :
    1
    2
    3
    4
    5
    6
    7
    loop
      for x in 1..1 loop
    .
         exit when ça_foire_inutile_d_insister;
    .
      end loop;
    end loop;

  12. #12
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    juin 2006
    Messages
    926
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations forums :
    Inscription : juin 2006
    Messages : 926
    Points : 415
    Points
    415
    Billets dans le blog
    1

    Par défaut

    Bonjour.

    Pour ma part, je préfère les constructions à base de "case".

    Code ada :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for index in index_type'first..index_type'last loop
       case condition is
            when ok =>
           
            when others =>
               null;
        end case;
    end loop;

  13. #13
    Membre régulier
    Profil pro
    Mathématicien
    Inscrit en
    mars 2012
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Mathématicien
    Secteur : Finance

    Informations forums :
    Inscription : mars 2012
    Messages : 70
    Points : 97
    Points
    97

    Par défaut loop...

    Code ada :
    1
    2
    for index in index_type'first..index_type'last loop
    ?
    Code ada :
    1
    2
    for index in index_type loop
    !

    Désolé, je n'ai pas pu résister

  14. #14
    Nouveau Membre du Club
    Inscrit en
    octobre 2010
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : octobre 2010
    Messages : 21
    Points : 29
    Points
    29

    Par défaut

    Citation Envoyé par HRS Voir le message
    cela ne marche pas trop bien si à l'intérieur du loop, il y a des conditions qui entrainent "next", d'autres qui entrainent "exit" à un ou plusieurs niveaux

    en fin de compte, la boucle "une fois" de Zerte répond le mieux au problème

    Code :
    1
    2
    3
    4
    5
    6
    7
    loop
      for x in 1..1 loop
    .
         exit when ça_foire_inutile_d_insister;
    .
      end loop;
    end loop;
    C'est justement la boucle 1..1 qui pose problème dans ce cas là : un exit dans le for fait sortir du for mais pas de la boucle infinie, donc si on laisse le code tel qu'il est on boucle ad libitum de façon assurée. Il faut impérativement effectuer un traitement à la sortie de la boucle for pour savoir si on est sorti pour la prochaine itération ou qu'on a atteint un cas d'arrêt. Alors qu'un exit dans le code utilisant une exception sortira bien de la boucle infinie, même si c'est très pénalisant niveau temps d'exécution de gérer une exception (comme supposé par poincare).

    Il est par contre vrai qu'au lieu de "null;" dans le bloc exception il faudrait plutôt mettre "gestion pour être sûr à 100% de ne pas boucler infiniment" car sinon ça pourrait se révéler problématique.

    EDIT : ou sinon de gérer ça juste avant de lever l'exception, ce qui serait plus pratique si on veut passer à l'itération suivante pour diverses raisons nécessitant un traitement particulier.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •