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

Ada Discussion :

equivalent "continue" en C, "next" en PERL


Sujet :

Ada

  1. #1
    HRS
    HRS est déconnecté
    Membre confirmé
    Avatar de HRS
    Inscrit en
    Mars 2002
    Messages
    677
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 677
    Points : 638
    Points
    638
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Architecte technique
    Inscrit en
    Mai 2007
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2007
    Messages : 48
    Points : 81
    Points
    81
    Par défaut
    Il n'y a pratiquement jamais besoin d'un GOTO en Ada.
    Faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 confirmé
    Avatar de HRS
    Inscrit en
    Mars 2002
    Messages
    677
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 677
    Points : 638
    Points
    638
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 actif

    Homme Profil pro
    Mathématicien et développeur
    Inscrit en
    Mars 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Mathématicien et développeur
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2012
    Messages : 132
    Points : 241
    Points
    241
    Billets dans le blog
    3
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 confirmé
    Avatar de HRS
    Inscrit en
    Mars 2002
    Messages
    677
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 677
    Points : 638
    Points
    638
    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
    Architecte technique
    Inscrit en
    Mai 2007
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2007
    Messages : 48
    Points : 81
    Points
    81
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 actif

    Homme Profil pro
    Mathématicien et développeur
    Inscrit en
    Mars 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Mathématicien et développeur
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2012
    Messages : 132
    Points : 241
    Points
    241
    Billets dans le blog
    3
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 confirmé
    Avatar de HRS
    Inscrit en
    Mars 2002
    Messages
    677
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 677
    Points : 638
    Points
    638
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    loop
     
    .
         next when ça_foire_inutile_d_insister;
    .
     
    end loop;

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 21
    Points : 30
    Points
    30
    Par défaut
    Vu que ça n'a pas encore été proposé, je suggère le recours à une exception :

    Code Ada : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Architecte technique
    Inscrit en
    Mai 2007
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2007
    Messages : 48
    Points : 81
    Points
    81
    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 confirmé
    Avatar de HRS
    Inscrit en
    Mars 2002
    Messages
    677
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 677
    Points : 638
    Points
    638
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Invité
    Invité(e)
    Par défaut
    Bonjour.

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

    Code ada : Sélectionner tout - Visualiser dans une fenêtre à part
    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 actif

    Homme Profil pro
    Mathématicien et développeur
    Inscrit en
    Mars 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Mathématicien et développeur
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2012
    Messages : 132
    Points : 241
    Points
    241
    Billets dans le blog
    3
    Par défaut loop...
    Code ada : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    for index in index_type'first..index_type'last loop
    ?
    Code ada : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    for index in index_type loop
    !

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

  14. #14
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 21
    Points : 30
    Points
    30
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

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