Précédent   Forum du club des développeurs et IT Pro > Autres langages > Autres langages > Ada
Ada Forum d'entraide sur la programmation en langage Ada
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 17/09/2012, 14h05   #1
HRS
Membre éprouvé
 
Avatar de HRS
 
Inscription : mars 2002
Messages : 623
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 623
Points : 494
Points : 494
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;
HRS est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/09/2012, 19h32   #2
poincare
Membre régulier
 
Avatar de poincare
 
Homme Henri Poincare
Architecte technique
Inscription : mai 2007
Messages : 44
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 : 44
Points : 72
Points : 72
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;
poincare est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/09/2012, 13h19   #3
HRS
Membre éprouvé
 
Avatar de HRS
 
Inscription : mars 2002
Messages : 623
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 623
Points : 494
Points : 494
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;
HRS est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/09/2012, 14h27   #4
Zerte
Membre régulier
 
Mathématicien
Inscription : mars 2012
Messages : 59
Détails du profil
Informations personnelles :
Localisation : Suisse

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

Informations forums :
Inscription : mars 2012
Messages : 59
Points : 82
Points : 82
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"
Zerte est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/09/2012, 18h09   #5
HRS
Membre éprouvé
 
Avatar de HRS
 
Inscription : mars 2002
Messages : 623
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 623
Points : 494
Points : 494
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"
HRS est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/09/2012, 19h15   #6
poincare
Membre régulier
 
Avatar de poincare
 
Homme Henri Poincare
Architecte technique
Inscription : mai 2007
Messages : 44
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 : 44
Points : 72
Points : 72
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;
poincare est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/09/2012, 02h17   #7
Zerte
Membre régulier
 
Mathématicien
Inscription : mars 2012
Messages : 59
Détails du profil
Informations personnelles :
Localisation : Suisse

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

Informations forums :
Inscription : mars 2012
Messages : 59
Points : 82
Points : 82
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;
Zerte est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2012, 15h59   #8
HRS
Membre éprouvé
 
Avatar de HRS
 
Inscription : mars 2002
Messages : 623
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 623
Points : 494
Points : 494
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;
HRS est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/09/2012, 00h06   #9
Jaizu
Nouveau Membre du Club
 
Inscription : octobre 2010
Messages : 21
Détails du profil
Informations forums :
Inscription : octobre 2010
Messages : 21
Points : 26
Points : 26
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;
Jaizu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/09/2012, 09h50   #10
poincare
Membre régulier
 
Avatar de poincare
 
Homme Henri Poincare
Architecte technique
Inscription : mai 2007
Messages : 44
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 : 44
Points : 72
Points : 72
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.
poincare est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/09/2012, 16h33   #11
HRS
Membre éprouvé
 
Avatar de HRS
 
Inscription : mars 2002
Messages : 623
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 623
Points : 494
Points : 494
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;
HRS est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/09/2012, 11h21   #12
jovalise
Membre éclairé
 
Inscription : juin 2006
Messages : 767
Détails du profil
Informations personnelles :
Âge : 43

Informations forums :
Inscription : juin 2006
Messages : 767
Points : 328
Points : 328
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;
__________________
Mon développement
jovalise est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/09/2012, 11h02   #13
Zerte
Membre régulier
 
Mathématicien
Inscription : mars 2012
Messages : 59
Détails du profil
Informations personnelles :
Localisation : Suisse

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

Informations forums :
Inscription : mars 2012
Messages : 59
Points : 82
Points : 82
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
Zerte est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2012, 17h39   #14
Jaizu
Nouveau Membre du Club
 
Inscription : octobre 2010
Messages : 21
Détails du profil
Informations forums :
Inscription : octobre 2010
Messages : 21
Points : 26
Points : 26
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.
Jaizu est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 08h36.


 
 
 
 
Partenaires

Hébergement Web