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 :

Hash et référence [perl6]


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé

    Homme Profil pro
    Statisticien
    Inscrit en
    Novembre 2010
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Statisticien

    Informations forums :
    Inscription : Novembre 2010
    Messages : 122
    Par défaut Hash et référence
    Bonjour,

    Voici un petit effet de bord auquel je ne m'attendais pas, et dont je ne comprends pas vraiment la raison;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/env perl6
    use v6;
     
    my %hash;       
    my $i=0;
    for 1..3 {
        $i++;
        %hash{$_}=($i,"$i");
    }   
    say %hash;
    donne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {1 => (3 1), 2 => (3 2), 3 => (3 3)}
    Le $i est donc passé en référence et non par valeur, contrairement à "$i".

    Un fois qu'on sait et qu'on accepte qu'on passe la référence, ça va. Mais pourquoi passe-t-on la référence... je trouve cela bizarre.

    Et en effet en perl5
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/perl
    use v5.10;
    use Data::Dump  qw(dump);
     
    my %hash;
    my $i=0;
    for (my $j=1;$j<=3;$j++) {
        $i++;
        $hash{$j}=($i,"$i");
    }
    say dump(%hash);

  2. #2
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Le $i est donc passé en référence et non par valeur, contrairement à "$i".

    Un fois qu'on sait et qu'on accepte qu'on passe la référence, ça va. Mais pourquoi passe-t-on la référence... je trouve cela bizarre.
    Ça n'a pas spécialement à voir avec les Hashs, mais plutôt avec les listes.

    En écrivant une liste avec une ou des variables (containers), les items de la liste ne sont pas les valeurs de ces containers, mais les containers eux-mêmes. Ce qui fait que lorsque je modifie la valeur de ces containers, je ne modifie pas la liste (qui est immutable), mais par contre j'obtiendrai les valeurs courantes de ces containers au moment de l'interpolation de la dite liste, comme son affichage ou son affectation à une variable sans qu'il y ait liaison (binding).

    En parcourant le livre "Learning Perl 6" de Brian D Foy, je me suis rendu compte que celui-ci évite soigneusement d'utiliser le terme "référence". Ce n'est pas pour rien: bien que sous le capot, tout se passe "par référence", Perl 6 met un point d'honneur à ce qu'on ait à s'en soucier le moins possible en s'appuyant sur le contexte pour "déréférencer" quand il le faut, bien plus que ne le fait Perl 5 où la notion de référence est très vite indispensable.

    Ce n'est donc pas un effet de bord mais une fonctionnalité plutôt pratique, si on veut faire varier une liste au cours du code. Mais quand on s'attend à ce que ces containers soient interpolés, c'est plutôt gênant !

    Heureusement la solution est simple: il suffit de placer la liste entre << et >> ou entre « (U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK) et » (U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK) et ainsi toutes les variables de la liste seront interpolées. Si on souhaite l'appliquer juste sur un item particulier, on peut aussi utiliser l'opérateur postfix de "décontainerisation" <>.

    Un peu de code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my $name = 'Philippe André';
    my $names = ( $name, 'Patrick Henry', 'Émile Pierre' );
     
    put $names.join(' | '); # Philippe André | Patrick Henry | Émile Pierre
    $name = 'Fabrice Michel';
    put $names.join(' | '); # Fabrice Michel | Patrick Henry | Émile Pierre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my $name = 'Philippe André';
    my $names = « $name, 'Patrick Henry', 'Émile Pierre' »;
     
    put $names.join(' | '); # Philippe André | Patrick Henry | Émile Pierre
    $name = 'Fabrice Michel';
    put $names.join(' | '); # Philippe André | Patrick Henry | Émile Pierre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my $name = 'Philippe André';
    my $names = ( $name<>, 'Patrick Henry', 'Émile Pierre' );
     
    put $names.join(' | '); # Philippe André | Patrick Henry | Émile Pierre
    $name = 'Fabrice Michel';
    put $names.join(' | '); # Philippe André | Patrick Henry | Émile Pierre
    Pourquoi le problème s'est-il révélé en affectant une liste à une valeur de hash? Et bien parce que cette affectation se fait avec liaison comme par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my $var1 = 'toto';
    my $var2 := $var1; # $var2 est un alors un alias de $var1
    $var1 = 'ziboinboin';
    put $var2; # ziboinboin



    À noter qu'en Perl 5, lors de la création d'un hash avec pour item des listes, on doit explicitement les passer par référence:
    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
    use strict;
    use warnings;
     
    use Data::Dump 'dump';
     
    my %hash;
     
    my $i = 0;
     
    for ('a'..'c') {
        $i++;
        $hash{$_} = [$i, "$i"];
        #           ^--------^--- les crochets en Perl 5 signalent une référence
    }
     
    print $hash{'a'}, "\n";
     
    print dump(%hash);

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

Discussions similaires

  1. Depiler un hash de références
    Par sohnic dans le forum Langage
    Réponses: 9
    Dernier message: 17/02/2019, 01h31
  2. tableau de tables de hash référence perl
    Par sbtrinity dans le forum Langage
    Réponses: 11
    Dernier message: 12/03/2012, 14h02
  3. références de hash
    Par Jasmine80 dans le forum Langage
    Réponses: 13
    Dernier message: 19/02/2010, 12h23
  4. hash -> références
    Par mauroyb0 dans le forum Langage
    Réponses: 7
    Dernier message: 14/06/2006, 20h29
  5. Référence en retour de fonction, à transformer en hash
    Par raoulchatigre dans le forum Langage
    Réponses: 4
    Dernier message: 15/07/2005, 14h24

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