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.