Références



Une référence en Perl est semblable à la notion de pointeur en C.

L'opérateur antislash a en Perl le même fonctionnement que & en C pour passer l'adresse d'une variable. Ex :

$var = 22 ;
$pt = \$var ; # $pt pointe sur l'emplacement mémoire qui contient $var

Il s'agit ici d'une référence physique, dans la mesure où il faut supprimer à la fois $var et $pt pour que l'emplacement où 22 est stocké soit libéré.

Pour utiliser la valeur contenue dans $pt, il faut utiliser la syntaxe $$pt parce qu'il s'agit ici d'une variable scalaire. Si l'on avait défini un pointeur vers un tableau ou un tableau associatif, il faudrait pour accéder à ces tableaux utiliser respectivement @$pt ou %$pt. En revanche, les éléments de ces tableaux devront être référencés avec $$pt(indice).
Si $tabref est une référence vers un tableau, on peut accéder au i-ème élément du tableau référencé par $tabref à l'aide de la syntaxe $tabref->[$i]. C'est une notation équivalente à ${$tabref}[$i], mais dont la compréhension est plus simple :-)
 

Tableaux multi-dimensionnels

Les crochets permettent de créer une référence vers un tableau multi-dimensionnel. Par exemple,

$tab = ['1', '2', ['titi','toto']];

construit un tableau (notons qu'il est cependant défini par $, comme une variable scalaire) dont les éléments sont accessibles par la syntaxe $tab->[indice1][indice2].

Dans cet exemple, on a $tab->[0] égal à 1, et $tab[2][1] égal à 'toto'.

Références à des sous-programmes

On utilise la syntaxe

$pt_fonc = sub { ... déclaration ...};

pour créer un pointeur sur un sous-programme.

Passer des tableaux en arguments à des sous-programmes

Il faut les passer par référence quand on doit passer plusieurs tableaux. En effet, la variable spéciale @_ concatène les éléments passés en argument, ce qui réduit l'ensemble des arguments à un seul "super-tableau". Par exemple,

#!/bin/perl
@pronoms = (je, tu, il);
@possessifs = (mon, ton, son);
$i = 0;
sub liste {
    my (@a, @b) = @_ ;
    foreach (@a) {
        print $a[$i]." ---- ".$b[$i]."\n";
        $i++ ;
    }
}
&liste (@pronoms, @possessifs);

va provoquer l'affichage suivant :

je ----
tu ----
il ----
mon ----
ton ----
son ----

La liste @possessifs est en fait concaténée à la liste @pronoms et "passée dans" @a ; @b ne contient alors rien ...

Si, en revanche, on passe les tableaux par référence de la manière suivante :

#!/bin/perl
@pronoms = (je, tu, il);
@possessifs = (mon, ton, son);
$i = 0;
sub liste {
    my ($a, $b) = @_ ;
    foreach (@$a) {
        print @$a[$i]." ---- ".@$b[$i]."\n";
        $i++ ;
    }
}
&liste (\@pronoms, \@possessifs);

on aura bien le résultat voulu :

je ---- mon
tu ---- ton
il ---- son
 

Lorsqu'on passe un (ou plusieurs) tableau(x), on peut le faire par référence, comme on vient de le voir, ou par typeglobs :

#!/bin/perl/
# Le script suivant ajoute 1 aux deux éléments d'un tableau.
@monTableau = (1,2);
print (@monTableau);
&routine(*monTableau);
print (@monTableau);
sub routine {
    local (*tmp) = @_ ;
    $tmp[0] += 1;
    $tmp[1] += 1;
}

Mais il vaut mieux utiliser my que local, et on ne peut pas faire de typeglob sur une variable locale (déclarée avec my), car les typeglobs représentent une entrée dans la table des symboles.

Typeglobs

Les typeglobs sont principalement utilisés, en-dehors de l'exemple que l'on vient de voir, pour :
- passer des filehandles en paramètres
- créer des fonctions dynamiquement
- faire des alias, comme le montre ce qui suit :

Si l'on veut que $var1 soit identique à $var2, que @var1 soit identique à @var2, et que %var1 soit identique à %var2, il faut écrire :
*var1 = *var2;

Si l'on veut faire un alias seulement sur $var1, il faut écrire :
*var1 = \$var2;
 

Utilisation d'accolades comme références symboliques

Exemple type d'utilisation :

$var1 = moto ;
print "${var1}cyclette\n";

Affiche : motocyclette.

Les accolades permettent l'évaluation de $var1 avant l'affichage.

On peut de la même manière provoquer l'évaluation directe d'un sous-programme :

#!/bin/perl
$a = 2;
$b = 3;
sub somme {
    my ($x,$y) = @_;
    $som = $x + $y;
    return ($som);
}
print "La somme est @{[&somme($a,$b)]} \n";

Le contenu de @{ } est évalué comme un bloc de code qui crée grâce aux crochets une référence à un tableau anonyme contenant le résultat de l'appel au sous-programme.
 

Deuxième exemple :

for $i (1..10) {
    @tab = 0..$i ;
    @{$a[$i]} = @tab ;
}

@{expr} suppose que expr est une référence vers un tableau. Donc $a[$i] contient une référence vers un tableau contenant tous les entiers de 0 à $i, tableau qui sera une copie de @tab. Alors que
$a[$i] = \@tab;
se contenterait de faire une référence vers @tab, sans le copier.
 

Troisième exemple : on souhaite afficher certaines valeurs d'un tableau associatif affectées à une clé donnée.

La première solution est la suivante :
foreach (@{$hash{'key'}) {
    ... # $_ contient la valeur courante
}
La deuxième est :
my @values = @{$hash{'key'}}[0..3];
si on veut les quatre premières valeurs
ou tout simplement
my @values = @{$hash{'key'}}[0..3];
si on les veut toutes.