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.