Outils pour utilisateurs

Outils du site


perl:references

Références

1. Introduction

Par conception, les listes et les hashes de Perl ne peuvent contenir que des éléments de type scalaire. C'est dommage, cela peut être à priori très utilie d'avoir des listes de listes, des hashes de listes, etc.

La solution consiste à pouvoir désigner n'importe quel type de donnée Perl (scalaire, liste, hash) à l'aide d'un scalaire spécial, la référence. Il s'agit d'un mécanisme analogue aux pointeurs en C ou C++.

L'utilisation des références demande des syntaxes particulières et différentes de ce que nous avons vu jusqu'ici, mais la manipulation des types de base reste bien entendu inchangée.

2. Créer des références

Obtenir la référence d'une variable

Si vous avez déjà des variables et que vous voulez obtenir leur référence, il suffit d'utiliser l'opérateur backslash :

  my $ref_scalaire = \$scalaire;
  my $ref_liste = \@liste;
  my $ref_hash = \%hash;

Définir directement des références

Il peut être utile d'obtenir des références sans créer au préalable une variable, par exemple pour initialiser des structures de données que l'on utilisera que via leur référence :

  my $ref_scalaire = \42;
  my $ref_liste = ["pierre", "papier", "ciseau"];
  my $ref_hash = { "nom" => "Perl", "date" => "1987" };

Notez l'utilisation des crochets et des accolades en lieu et place des parenthèses.

3. Utilisation des références

La référence en tant que telle ne représente pas la structure qu'elle désigne, par exemple si on l'affiche :

  my $ref = \42;
  print "$ref\n"; # Affiche SCALAR(0x814f5e8)

Déréférencement

Pour manipuler la structure de donnée référencée, on préfixe par le symbole du type référencé et on met la référence entre accolades :

  my $ref = \42;
  print "${$ref}\n"; # Affiche 42
 
  my $ref_liste = ["pierre", "papier", "ciseau"];
  print join(" - ", @{$ref_liste});
  print ${$ref_liste}[0];
 
  my $ref_hash = { "nom" => "Perl", "date" => "1987" };
  print join(" - ", keys %{$ref_hash});
  print %{$ref_hash}{"nom"};

Souvent, on veut juste extraire un élément d'une liste ou d'un hash, et cette syntaxe est trop lourde et peu lisible. Dans ce cas, il existe un raccourci :

  my $ref_liste = ["pierre", "papier", "ciseau"];
  print $ref_liste->[0];
 
  my $ref_hash = { "nom" => "Perl", "date" => "1987" };
  print $ref_hash->{"nom"};

Il existe enfin un dernier raccourci: il est possible de ne pas spécifier la flèche entre deux indiçages de liste (ceci permettant d'implémenter les tableaux multidimensionnels sans s'arracher les cheveux) :

  my @matrice = (
  [1, 0, 2],
  [0, 1, 0],
  [3, 0, 1]
  );
  print ${$matrice[$_]}[$_] foreach (1..3);
  print $matrice[$_]->[$_] foreach (1..3);
  print $matrice[$_][$_] foreach (1..3);

Copie

Si on copie des références, on ne copie pas les structures de données qu'elles désignent. On obtient simplement deux noms pour accéder aux mêmes données :

  my $number = 42;
  my $ref1 = \$number;
  ${$ref1} = 33; # $number vaut 33
 
  my $ref2 = $ref1;
  ${$ref2} = 57; # $number vaut 57

Exemples

Avec un hash de listes :

  my %notes = (
  "Pierre" => [15, 12, 10.5],
  "Jean" => [9, 18, 11]
  );
  print "La dernière note de Pierre est ${$notes{"Pierre"}}[0]";
  print "La dernière note de Pierre est $notes{"Pierre"}->[0]";

Ou alors une liste de hashes: quand on parcourt la liste, les éléments sont des références, on utilise donc de préférence la notation

$_->... :
  my @eleves = (
  { "nom" => "Pierre", "moyenne" => 12.5, niveau => "2" },
  { "nom" => "Jean", "moyenne" => 10.5, niveau => "1" },
  );
  foreach (@eleves) {
  print "${$_}{'nom'} a une moyenne de ${$_}{'moyenne'}";
  print "$_->{'nom'} a une moyenne de $_->{'moyenne'}";
  }

Enfin, les références sont particulièrement utiles pour pouvoir passer des listes et des hashes à des fonctions sans que ces dernières soit mises à plat dans la liste @_ :

  sub rapport {
  my $temperatures = shift;
  my $precipitation = shift;
  print "Mois $_: $temperatures->[$_]°C, $precipitation->[$_]\n" foreach
  (1..12);
  }

Références à des références :

my $maison = "maison particulière préfabriquée";
my @voitures = ("Citroën","Peugeot","Renault","Porsche");
my %famille = (femme => "Fanny", fille => "Anne", fils => "Florian");
my %pointeur_hash = (
     pointeur_maison => \$maison,
     pointeur_voiture => \@voitures,
     pointeur_famille => \%famille
);
my $pointeur = \%pointeur_hash;
 
print "(1.) $pointeur->{pointeur_maison}\n";
print "(2.) ${$pointeur->{pointeur_maison}}\n";
print "(3.) $pointeur->{pointeur_voiture}\n";
print "(4.) @{$pointeur->{pointeur_voiture}}\n";
print "(5.) $pointeur->{pointeur_voiture}->[2]\n";
print "(6.) $pointeur->{pointeur_voiture}[3]\n";
print "(7.) $pointeur->{pointeur_famille}\n";
print "(8.)", %{$pointeur->{pointeur_famille}},"\n";
print "(9.) $pointeur->{pointeur_famille}->{femme}\n";
print "(10.) $pointeur->{pointeur_famille}{fils}\n"

Affichera :

(1.) SCALAR(0x8154558)<br>
(2.) maison particulière préfabriquée<br>
(3.) ARRAY(0x8154588)<br>
(4.) Citr&euml;n Peugeot Renault Porsche<br>
(5.) Renault<br>
(6.) Porsche<br>
(7.) HASH(0x8154a44)<br>
(8.) filleAnnefilsFlorianfemmeFanny<br>
(9.) Fanny<br>
(10.) Florian<br>
perl/references.txt · Dernière modification : 2013/03/12 23:33 de root