Ludovic ROLAND

Blog technique sur mes expériences de développeur.

Perl 5 : Introduction aux références

26 mars 2021

Ce billet est une introduction aux références en Perl.

S’agissant d’une notion une peu délicate, je vais tenter de vous expliquer de manière ludique de quoi il en retourne et comment les utiliser correctement.

Une référence, c’est quoi ?

Rappel sur les variables

Pour rappel, une variable est une petite chose qui permet de stocker à un moment donné de votre programme des informations comme par exemple l’âge de l’utilisateur, son nom, ou d’autres données bien plus complexes.

Lors de l’exécution de votre programme, ces variables sont stockées dans la mémoire vive de votre ordinateur (la RAM). Ainsi, à chaque variable correspond un emplacement bien précis dans la mémoire de votre machine. Cet emplacement est repéré par ce que l’on appelle une adresse qui lui est unique !

Lors de l’exécution de votre programme, une table de symbole est créée afin de faire le lien entre vos variables et leur emplacement dans la mémoire de votre machine.

L’adresse d’une variable s’obtient grâce au symbole \ qui précède son nom.

Voyons immédiatement un exemple :

# !/usr/bin/perl

use strict;

my $var = 2;

print 'La valeur de var est : '.$var."\n";
print 'L\'adresse de la variable var est : '.\$var."\n";

En exécutant ce petit programme, vous devriez alors obtenir quelque chose comme ça :

> perl reference.pl
La valeur de var est : 2
L'adresse de la variable var est : SCALAR(0x81e3f00)

Si l’on s’intéresse à la seconde ligne, nous constatons l’apparition de 2 informations :

  • entre parenthèse, nous avons l’adresse de la variable dans la mémoire vive de l’ordinateur sous sa forme hexadécimal (0x81e3f00) ;
  • le type de la référence, à savoir ici une référence de type scalaire (SCALAR).

Le fait que le type de la variable soit précisé, devrait vous mettre la puce à l’oreille. En effet, ceci indique clairement qu’il est également possible d’obtenir l’adresse de tableaux, de tables de hachage ou encore de fonctions. A noter que nous n’étudierons pas ce dernier cas.

Je vous propose d’ailleurs d’écrire tout de suite un petit programme permettant d’illustrer ces derniers propos :

# !/usr/bin/perl

use strict;

my $scalaire;
my @tableau;
my %hachage;

print 'L\'adresse du scalaire est : '.\$scalaire."\n";
print 'L\'adresse du tableau est : '.\@tableau."\n";
print 'L\'adresse de la table de hachage est : '.\%hachage."\n";

Vous devriez alors obtenir quelque chose comme ça :

> perl reference.pl
L'adresse du scalaire est : SCALAR(0x84eff00)
L'adresse du tableau est : ARRAY(0x84eff40)
L'adresse de la table de hachage est : HASH(0x84eff70)

Maintenant que vous êtes au point avec la notion d’adresse d’une variable, nous allons pouvoir passer aux références à proprement parler !

Utiliser des références

Définition générale

Si vous avez bien compris les explications précédentes, la définition d’un référence tient en une ligne. Il s’agit en réalité une variable un peu particulière qui permet de stocker l’adresse mémoire d’une variable de type scalaire, tableau, table de hachage, etc.

Le fait de stocker l’adresse mémoire va nous permettre de travailler directement avec la valeur des variables en passant directement par leur emplacement dans la mémoire.

Créer une référence

Une référence se déclare comme une variable de type scalaire, et s’initialise avec une adresse mémoire.

Voyons tout de suite un exemple :

# !/usr/bin/perl

use strict;

my $scalaire = 2;
my $ref = \$scalaire;

print 'L\'adresse du scalaire est : '.\$scalaire."\n";
print 'La valeur de la référence est est : '.$ref."\n";

Si tout ce que je vous ai raconté jusque là est vrai, nous devrions voir s’affiche à l’écran la même adresse mémoire. Voyons tout de suite ce que ça donne :

> perl reference.pl
L'adresse du scalaire est : SCALAR(0x8415f00)
La valeur de la référence est est : SCALAR(0x8415f00)

Bingo ! Tout semble fonctionner !

Un peu de vocabulaire

Avant de continuer, j’aimerais faire quelques commentaires sur le vocabulaire à utiliser afin que vous ne soyez pas perdu dans la suite de ce chapitre.

On dit que “la variable $scalaire a pour valeur 2”. Pour les références, on dit que “la référence $ref a pour valeur 0x8415f00 et contient 2”.

Vous faites bien de poser la question, puisque c’est justement ce dont on va parler dans la suite de ce chapitre !

Références sur scalaire

Modélisation de la référence

Nous venons de le voir, pour déclarer et initialiser une référence sur une variable scalaire, il suffit de faire :

my $scalaire = 2;
my $ref = \$scalaire;

Pour répondre à cette question, je vous propose un petit schéma.

La variable $ref a pour valeur l’adresse de la variable $scalaire. On dit que $ref pointe vers $scalaire (ce qui est représenté par la flèche sur le schéma).

La conséquence est que l’on va pouvoir manipuler $scalaire via $ref. C’est d’ailleurs ce que nous allons voir maintenant !

Manipuler la référence

Je vous propose de revenir à notre exemple :

my $scalaire = 2;
my $ref = \$scalaire;

Comme je l’ai déjà dit plusieurs fois, la valeur de la variable $ref est l’adresse en mémoire de la variable$scalaire. Ce qui nous intéresse nous, c’est d’avoir accès au contenu de la variable $ref, c’est-à-dire la valeur de la variable $scalaire (ici 2).

Pour celà, il existe une écriture simple. Il suffit de précéder notre variable $ref par le sigil de ce qu’elle contient (dans notre cas un scalaire, donc le sigil sera $).

Ainsi, pour accéder au contenu de la variable $ref, on utilisera $$ref.

Voyons immédiatement un exemple :

# !/usr/bin/perl

use strict;

my $scalaire = 2;
my $ref = \$scalaire;

print 'L\'adresse du scalaire est : '.\$scalaire."\n";
print 'La valeur de la référence est : '.$ref."\n";
print 'La valeur du scalaire est : '.$scalaire."\n";
print 'Le contenu de la référence est : '.$$ref."\n";

Lors de l’exécution, vous devriez avoir quelque chose comme ça :

> perl reference.pl
L'adresse du scalaire est : SCALAR(0x88c8f00)
La valeur de la référence est : SCALAR(0x88c8f00)
La valeur du scalaire est : 2
Le contenu de la référence est : 2

Nous avons bien accès à la valeur de la variable $scalaire via l’écriture $$ref. A partir de ce point, il est tout à fait possible de manipuler ce contenu. A savoir que si l’on modifie $$ref, on modifie également $scalaire.

Voici un exemple à l’appui :

# !/usr/bin/perl

use strict;

my $scalaire = 2;
my $ref = \$scalaire;

print 'La valeur du scalaire est : '.$scalaire."\n";
print 'Le contenu de la référence est : '.$$ref."\n";

$$ref = 12;

print 'La valeur du scalaire est : '.$scalaire."\n";
print 'Le contenu de la référence est : '.$$ref."\n";

Lors de l’exécution, nous obtenons :

> perl reference.pl
La valeur du scalaire est : 2
Le contenu de la référence est : 2
La valeur du scalaire est : 12
Le contenu de la référence est : 12

Bingo ! En modifiant le contenu de $ref, on modifie bien la valeur de la variable $scalaire.

Maintenant que nous venons de voir les références sur les scalaires, je vous propose de passer aux références sur les tableaux !

Références sur tableau

Modélisation de la référence

Comme vous le savez déjà, pour déclarer et initialiser une référence sur un tableau, il suffit de faire :

my @tableau = (1, 2, 3);
my $ref = \@tableau;

Pour répondre à cette question, je vous propose un petit schéma.

La variable $ref a pour valeur l’adresse du tableau @tableau. On dit que $ref pointe vers @tableau (ce qui est représenté par la flèche sur le schéma).

La conséquence est que l’on va pouvoir manipuler @tableau via $ref. C’est d’ailleurs ce que nous allons voir maintenant !

Manipuler la référence

Je vous propose de revenir à notre exemple :

my @tableau = (1, 2, 3);
my $ref = \@tableau;

Comme je l’ai déjà dit plusieurs fois, la valeur de la variable $ref est l’adresse en mémoire du tableau @tableau. Ce qui nous intéresse nous, c’est d’avoir accès au contenu de la variable $ref, c’est-à-dire les valeurs stockées dans le tableau @tableau (ici 2).

Pour celà, il existe une écriture simple. Il suffit de précéder notre variable $ref par le sigil de ce qu’elle contient (dans notre cas un tableau, donc le sigil sera @).

Ainsi, pour accéder au contenu de la variable $ref, on utilisera @$ref.

Voyons immédiatement un exemple :

# !/usr/bin/perl

use strict;

my @tableau = (1, 2, 3);
my $ref = \@tableau;

print 'L\'adresse du tableau est : '.\@tableau."\n";
print 'La valeur de la référence est : '.$ref."\n";

print 'La valeur du tableau est : ';
foreach my $elt (@tableau) {
  print "\t".$elt;
}

print "\n".'Le contenu de la référence est : ';
foreach my $elt (@$ref) {
  print "\t".$elt;
}

print "\n";

Lors de l’exécution, vous devriez avoir quelque chose comme ça :

> perl reference.pl
L'adresse du tableau est : ARRAY(0x84c2f20)
La valeur de la référence est : ARRAY(0x84c2f20)
La valeur du tableau est :       1        2        3
Le contenu de la référence est : 1        2        3

Nous avons bien accès aux valeurs du tableau @tableau via l’écriture @$ref. A partir de maintenant, il est tout à fait possible de manipuler ce contenu. A savoir que si l’on modifie @$ref, on modifie également @tableau.

Voici un exemple à l’appui :

# !/usr/bin/perl

use strict;

my @tableau = (1, 2, 3);
my $ref = \@tableau;

print 'L\'adresse du tableau est : '.\@tableau."\n";
print 'La valeur de la référence est : '.$ref."\n";

print 'La valeur du tableau est : ';
foreach my $elt (@tableau) {
  print "\t".$elt;
}

print "\n".'Le contenu de la référence est : ';
foreach my $elt (@$ref) {
  print "\t".$elt;
}

for(my $i=0; $i<@$ref; $i++) {
  $$ref[$i] = 12;
}

print "\n".'La valeur du tableau est : ';
foreach my $elt (@tableau) {
  print "\t".$elt;
}

print "\n".'Le contenu de la référence est : ';
foreach my $elt (@$ref) {
  print "\t".$elt;
}

print "\n";

Lors de l’exécution, nous obtenons :

> perl reference.pl
L'adresse du tableau est : ARRAY(0x9080f20)
La valeur de la référence est : ARRAY(0x9080f20)
La valeur du tableau est :       1        2        3
Le contenu de la référence est : 1        2        3
La valeur du tableau est :       12        12        12
Le contenu de la référence est : 12        12        12

Bingo ! En modifiant le contenu de $ref , on modifie bien la valeur du tableau @tableau.

Maintenant que nous venons de voir les références sur les tableaux, je vous propose de passer aux références sur les tables de hachages !

Références sur table de hachage

Modélisation de la référence

Comme vous le savez déjà, pour déclarer et initialiser une référence sur une table de hachage, il suffit de faire :

my %hash = ('Bob' => '001', 'Wapiti89' => '002');
my $ref = \%hash;

Comment représenter graphiquement la relation qui existe entre cette table de hashage et cette variable ?

Pour répondre à cette question, je vous propose un petit schéma.

La variable $ref a pour valeur l’adresse de la table de hachage %hash. On dit que $ref pointe vers %hash (ce qui est représenté par la flèche sur le schéma).

La conséquence est que l’on va pouvoir manipuler %hash via $ref. C’est d’ailleurs ce que nous allons voir maintenant !

Manipuler la référence

Je vous propose de revenir à notre exemple :

my %hash = ('Bob' => '001', 'Wapiti89' => '002',);
my $ref = \%hash;

Comme je l’ai déjà dit plusieurs fois, la valeur de la variable$ref est l’adresse en mémoire de la table de hachage %hash. Ce qui nous intéresse nous, c’est d’avoir accès au contenu de la variable $ref, c’est-à-dire les valeurs stockées dans la table de hachage %hash.

Pour celà, il existe une écriture simple. Il suffit de précéder notre variable $ref par le sigil de ce qu’elle contient (dans notre cas un tableau, donc le sigil sera %).

Ainsi, pour accéder au contenu de la variable $ref, on utilisera %$ref.

Voyons immédiatement un exemple :

# !/usr/bin/perl

use strict;

my %hash = ('Bob' => '001', 'Wapiti89' => '002',);
my $ref = \%hash;

print 'L\'adresse de ma table de hachage est : '.\%hash."\n";
print 'La valeur de la référence est : '.$ref."\n";

print 'La valeur de la table de hachage est : ';
foreach my $key (keys %hash) {
  print 'Clef='.$key.', Valeurs='.$hash{$key}."\t";
}

print "\n".'Le contenu de la référence est : ';
foreach my $key (keys %$ref) {
  print 'Clef='.$key.', Valeurs='.$$ref{$key}."\t";
}

print "\n";

Lors de l’exécution, vous devriez avoir quelque chose comme ça :

> perl reference.pl
L'adresse de ma table de hachage est : HASH(0x977ff20)
La valeur de la référence est : HASH(0x977ff20)
La valeur de la table de hachage est : Clef=Bob, Valeurs=001        Clef=Wapiti89, Valeurs=002 
Le contenu de la référence est :       Clef=Bob, Valeurs=001        Clef=Wapiti89, Valeurs=002

Nous avons bien accès aux valeurs de la table de hachage %hash via l’écriture %$ref. A partir de maintenant, il est tout à fait possible de manipuler ce contenu. A savoir que si l’on modifie %$ref, on modifie également %hash.

Voici un exemple à l’appui :

# !/usr/bin/perl

use strict;

my %hash = ('Bob' => '001', 'Wapiti89' => '002',);
my $ref = \%hash;

print 'L\'adresse de ma table de hachage est : '.\%hash."\n";
print 'La valeur de la référence est : '.$ref."\n";

print 'La valeur de la table de hachage est : ';
foreach my $key (keys %hash) {
  print 'Clef='.$key.', Valeurs='.$hash{$key}."\t";
}

print "\n".'Le contenu de la référence est : ';
foreach my $key (keys %$ref) {
  print 'Clef='.$key.', Valeurs='.$$ref{$key}."\t";
}

foreach my $key (keys %$ref) {
  $$ref{$key} = 'Coucou';
}

print "\n".'La valeur de la table de hachage est : ';
foreach my $key (keys %hash) {
  print 'Clef='.$key.', Valeurs='.$hash{$key}."\t";
}

print "\n".'Le contenu de la référence est : ';
foreach my $key (keys %$ref) {
  print 'Clef='.$key.', Valeurs='.$$ref{$key}."\t";
}

print "\n";

Lors de l’exécution, nous obtenons :

> perl reference.pl
L'adresse de ma table de hachage est : HASH(0x9821f20)
La valeur de la référence est : HASH(0x9821f20)
La valeur de la table de hachage est : Clef=Bob, Valeurs=001        Clef=Wapiti89, Valeurs=002
Le contenu de la référence est :       Clef=Bob, Valeurs=001        Clef=Wapiti89, Valeurs=002
La valeur de la table de hachage est : Clef=Bob, Valeurs=Coucou     Clef=Wapiti89, Valeurs=Coucou
Le contenu de la référence est :       Clef=Bob, Valeurs=Coucou     Clef=Wapiti89, Valeurs=Coucou

Vous êtes maintenant au point également sur les références sur les tables de hachages !

Bien évidemment, ce chapitre n’est qu’une introduction aux références, mais devrait vous suffire à les comprendre.

Commentaires