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

Langage Perl Discussion :

[langage] foreach, last et valeurs de sortie


Sujet :

Langage Perl

  1. #1
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut [langage] foreach, last et valeurs de sortie
    Bonjour à tous.
    Je suis sous Active Perl 5.8.3.809.

    Soit le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    my @xdas = ( 't1', 't2', 't3' );
    my ( $it, $tmp );
    foreach $it (@xdas) {
    	$tmp = $it;
    	last if $it ge 't2';
    }
     
    print "\$it = $it  --  \$tmp = $tmp";
    Sortie attendue : "$it = t2 -- $tmp = t2"
    Sortie obtenue : "$it = -- $tmp = t2"
    En sortant du foreach, $it passe undef.

    Comment se fesse ????

  2. #2
    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
    En fait, foreach fait un local (ou un my, je ne saurais me prononcer) caché de ton $it quand tu l'utilises comme itérateur, comme le montre ce code :
    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
     
    #!/usr/bin/perl
    use strict; use warnings;
     
    my @xdas = ( 't1', 't2', 't3' );
    my ( $it, $tmp );
    my $refit = \$it;
    foreach $it (@xdas) {
       $tmp = $it;
       print $$refit;
       print $it;
       last if $it ge 't2';
    }
     
    print "\$it = $it  --  \$tmp = $tmp";
    On constate que le $it originel reste bien indéfini à l'intérieur de la boucle... C'est sans doute pour éviter qu'un itérateur intempestif ne rentre en conflit avec une autre variable par erreur.

    --
    Jedaï

  3. #3
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    Citation Envoyé par Jedai
    En fait, foreach fait un local (ou un my, je ne saurais me prononcer) caché de ton $it quand tu l'utilises comme itérateur
    En effet...
    C'est vraiment une horreur. Qui a pondu des specs aussi inutilement piégeuses ????

  4. #4
    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
    Je trouve que c'est plutôt une bonne chose, un itérateur est fait pour être utilisé dans sa propre boucle, pas à l'extérieur. De plus on a souvent tendance à utiliser des termes génériques pour les itérateurs, le même plusieurs fois par script, ce qui rend plutôt fastidieux la compréhension du code si on utilise ce nom en dehors de sa boucle pour désigner l'itérateur lui-même.
    Je suppose que tu sais que tu peux utiliser la syntaxe suivante, plus claire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    foreach my $it ( @array ) {
      #code
    }
    Ainsi $it n'est disponible que dans la boucle (ou en tout cas, il est clair qu'il ne s'agit pas du même $it qu'à l'extérieur de la boucle).

    --
    Jedaï

  5. #5
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    C'est vrai qu'il peut y avoir des problèmes de collision de noms. Mais à mon avis, il suffit de s'astreindre à la discipline du "use stricts" et du "my" pour éviter ce genre de soucis, disons dans 99% des cas.

    Pour ce qui est de la syntaxe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach my $it (@arr ) {...}
    je t'accorde volontiers qu'elle est plus propre. Seulement, il est impossible d'utiliser le $it après la fin de la boucle, puisqu'il est local au foreach (et là au moins c'est clair ) C'est pourquoi de temps à autre, quand j'ai besoin de référencer l'itérateur à l'extérieur de la boucle, je le déclare avant.

    A ce propos, un détail me turlupine, que je vais vérifier demain (sur ma machine au bureau) avant d'activer le bouton [résolu]. Car en effet, il me semble bien que la boucle qui me pose problème ici, sur ma machine perso, tourne très bien là-bas. Faute de quoi, comme j'utilise souvent cette tournure (qui fonctionne fort bien dans mes langages de programmation habituels), je pense que j'aurais déjà eu des surprises...

    Vérification et compte-rendu demain si tout va bien 8)

  6. #6
    Membre expert
    Avatar de 2Eurocents
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 177
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 177
    Points : 3 166
    Points
    3 166
    Par défaut
    Le fait que la variable de parcours du foreach soit "localisé" à la boucle est documenté et justifié (dans la partie perlsyn du man et de la doc, si je me souviens bien). Une justification en est que cela permet d'utiliser cette variable comme une 'lvalue', un réceptacle d'affectation, tout en conservant la cohérence du parcours de boucle.

    Il est donc possible de modifier le tableau parcouru de cette manière ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    foreach my $p (@t) 
    {
      $p = "---[ $p ]---";
    }
    Par contre, il faut rappeler que la modification de @t durant la boucle est une opération dangereuse aux résultats totalement imprévisibles (enfin, surtout du point de vue fonctionnel)

    Pour ce qui est de récupérer l'élément en cours de parcours, il n'y a pas d'autre choix que de passer par une variable externe qui soit affectée dans la boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    use strict; 
     
    my @t=qw(aaa bbb ccc ddd eee);
    my $p; 
    foreach my $pb (@t) 
    { 
      print "$pb\n" ; 
      $p = $pb ; 
      last if ( $pb eq "ccc" ) ; 
    } 
    print "[$p]\n";
    ou de passer par une boucle explicite, sur les indices du tableau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    use strict; 
    my @t=qw(aaa bbb ccc ddd eee);
    my $pb ; 
    for ( $pb=0 ; $pb < @t ; $pb++) 
    { 
      print "@t[$pb]\n" ; 
      last if ( $pb == 2 ) ; 
    }
    print "[@t[$pb]]\n";
    Mais dans ce cas, vu la syntaxe du code et le manque d'abstraction, à quoi bon faire du PERL
    La FAQ Perl est par ici
    : La fonction "Rechercher", on aurait dû la nommer "Retrouver" - essayez et vous verrez pourquoi !

  7. #7
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    Hé bien comme on peut s'en douter, le détail qui me turlupinait n'est qu'un effet de mon imagination. Peut-être vais-je envisager d'arrêter l'absinthe...

    Merci pour les infos en tout cas ! 8)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. mauvaises valeurs en sortie
    Par emprex dans le forum Débuter
    Réponses: 9
    Dernier message: 07/02/2008, 19h25
  2. Foreach + trier par valeur
    Par ciel65 dans le forum Langage
    Réponses: 11
    Dernier message: 21/06/2007, 13h33
  3. [Tableaux] Foreach renvoie des valeurs double en php4
    Par Dantahoua dans le forum Langage
    Réponses: 5
    Dernier message: 10/04/2007, 17h49
  4. [JSP] addition deux valeurs en sortie d'une jsp
    Par LESOLEIL dans le forum Servlets/JSP
    Réponses: 11
    Dernier message: 08/06/2005, 11h13
  5. récupérer la valeur de sortie d'un thread
    Par jakouz dans le forum Langage
    Réponses: 3
    Dernier message: 31/07/2002, 11h28

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