SELFHTML/Aides à la navigation CGI/Perl Éléments de langage Perl |
Si vous vous y connaissez dans le langage C, vous savez ce que sont les pointeurs, et combien ils rendent la programmation efficace. Les références sont des pointeurs sur d'autres contenus par exemple des variables définies auparavant (peu importe qu'il s'agisse de scalaires, de listes ou bien de Hashes). Par des références, vous pouvez adresser le contenu d'une variable scalaire simple, d'une liste ou d'un Hash exactement comme par le nom d'origine. De plus. vous pouvez poser des références à des sous-programmes. Les références sont des scalaires qui ne sauvegardent cependant aucune "valeur exploitable", mais uniquement des adresses de la mémoire de travail d'autres variables ou de sous-programmes.
Pour des débutants il n'est pas d'abord bien clair à quoi peuvent servir ces références ou pointeurs. Car les avantages des références résident d'une part dans un domaine que Perl épargne autrement - à savoir la gestion efficace de la mémoire de travail. Cela exige moins de mémoire de travail et de charge de calcul de transmettre à une fonction, non pas une chaîne de caractères avec plusieurs milliers de caractères, mais seulement une référence à cette chaîne de caractères. D'autre part, les références sont tout indiquées quand il s'agit d'élaborer des structures de données complexes.
Les références sont également mises en œuvre avant tout dans la programmation orientée sur l'objet , qui est également possible avec Perl depuis la version 5 de l'interpréteur Perl. Ainsi, l'accès aux méthodes (fonctions et sous-programmes) et aux propriétés (variables) a lieu par les références. Il y a même beaucoup de modules modernes qui utilisent cette technique et utiliser ces modules revient à dire travailler avec des références. C'est pourquoi, il est avantageux de toutes façons de travailler avec des références.
La manière de travailler des références en Perl est différente par exemple de celle du langage C classique. Les "pointeurs abandonnés" de mauvaise réputation, donc les références dont la durée de vie est plus longue que ce sur quoi elles pointent et qui peut conduire en C à des états incontrôlés du programme, n'existent pas en Perl.. Là, la valeur sur laquelle pointe la référence est conservé en mémoire aussi longtemps que subsiste une référence à cette valeur.
C'est pour cette raison entre autres qu'une arithmétique des pointeurs (effectuer des calculs avec des pointeurs), telle qu'elle est souvent pratiquée en C n'est pas possible en Perl.
Vous pouvez créer un pointeur sur une scalaire et accéder par ce pointeur à la scalaire et à la valeur qui y est sauvegardée.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); my $phrase = "HTML - How To Make Love"; my $pointeur_phrase = \$phrase; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "Type de variable et adresse mémoire de \$phrase: $pointeur_phrase<br>\n"; print "Contenu de \$phrase: ${$pointeur_phrase}\n"; print "</body></html>\n"; |
L'exemple définit d'abord une scalaire habituelle nommée $phrase
déclarée et initialisée avec une valeur. Ensuite est déclarée une référence à cette scalaire. La référence reçoit dans l'exemple le nom $pointeur_phrase
. Il s'agit ici du point de vue syntaxe, visiblement d'une scalaire. Ce qui fait de cette scalaire une référence c'est la valeur qui lui est attribuée lors de son initialisation. La valeur affectée \$phrase
signale à Perl, par la barre oblique inversée qui la précède, que dans $pointeur_phrase
doit être sauvegardée la référence à $phrase
. Si la barre oblique inversée manquait, $pointeur_phrase
se verrait simplement affecter une copie de la valeur de $phrase
.
Le script en exemple envoie du code HTML au navigateur appelant. Ici, il sort deux informations: d'une part le contenu de $pointeur_phrase
(afin que l'on voit ce qui est sauvegardé dans une telle référence - la valeur sortie contient quelque chose comme SCALAR(0xb67d20)
), et d'autre part le contenu de $phrase
, cependant pas par $phrase
même, mais à l'aide de la référence $pointeur_phrase
. Le code sorti dans l'exemple contient en outre une autre petite embûche qui peut déconcerter: à l'endroit où \$phrase
est placé dans l'instruction print
, la barre oblique inversée a une autre signification qu'auparavant lors de l'initialisation de la référence! À cet endroit la barre oblique inversée sert à masquer le signe $
. En le masquant on obtient qu'à cet endroit la chaîne de caractères $phrase
soit sortie et non pas par exemple la valeur sauvegardée dans $phrase
.
Pour pouvoir accéder avec une référence à la valeur sauvegardée, vous devez utiliser la syntaxe comme montré dans l'exemple avec ${$pointeur_phrase}
. La référence dans le cas de $pointeur_phrase
, est notée ici entre parenthèses accolades, et précédant immédiatement la parenthèse accolade d'ouverture est encore noté un signe dollar. ${$pointeur_phrase}
donne donc dans l'exemple HTML - How To Make Love
.
La syntaxe pour déréférencer avec les parenthèses accolades est la variante qui fonctionne dans tous les cas. Perl propose aussi la possibilité d'abréger la notation. au lieu de ${$pointeur_phrase}
vous pouvez également noter $$pointeur_phrase
, si ça ne prête pas à confusion dans le contexte.
Vous pouvez créer un pointeur sur un Array et accéder par ce pointeur à tous ses éléments.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); my @phrases = ( "HTML - How To Make Love. ", "XHTML - Extended How To Make Love. ", "XML - Extended Making Love." ); my $pointeur_phrases = \@phrases; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "Type de variable et adresse mémoire de \@phrases: $pointeur_phrases<br>\n"; print "contenu de \@phrases: @{$pointeur_phrases} <br>\n"; print "contenu de \$phrases[2]: $pointeur_phrases->[2] <br>\n"; print "</body></html>\n"; |
Dans l'exemple est d'abord déclaré un tableau nommé @phrases
et initialisé avec des valeurs de départ. Ensuite est déclarée une référence à ce tableau, nommée $pointeur_phrases
. La référence proprement dite est une scalaire, ce qu'on remarque au signe dollar qui le précède. Une référence au tableau est affectée à cette scalaire par la valeur affectée \@phrases
. La barre oblique inversée signale à Perl qu'il s'agit d'une référence. Si la barre oblique inversée manquait, $pointeur_phrases
ne sauvegarderait d'ailleurs que le nombre des éléments de tableau de @phrases
!
Le script en exemple envoie du code HTML au navigateur appelant et sort ici différentes données. Dans la première instruction print
est sortie pour une meilleure compréhension, la valeur sauvegardée de la référence $pointeur_phrases
- il s'agit de quelque chose comme ARRAY(0xb65b28)
.
La deuxième instruction print
sort le contenu complet du tableau. il est accédé au tableau, comme un tout par la référence avec la syntaxe @{$pointeur_phrases}
. La référence figure donc dans des parenthèses accolades précédée immédiatement d'un signe "chez" @
qui désigne la liste.
Dans la troisième instruction print
est sortie un élément déterminé de @phrases
à savoir le troisième élément de la liste. Noté directement, cet élément pourrait être adressé avec $phrases[2]
. Dans l'exemple cependant, il est adressé avec la référence et la syntaxe est ici $pointeur_phrases->[2]
. La référence est donc notée suivie de l'opérateur flèche ->
et de l'élément de liste désiré entre crochets. Il est important ici que dans ce contexte (donc à l'intérieur de chaînes de caractères, ) aucun espace ne soit placé à l'intérieur de $pointeur_phrases->[2]
.
Les barres obliques inversées devant \@phrases
et \$phrases[2]
dans les instructions print
n'ont, comme dans l'exemple sur les scalaires, rien à voir avec les références, mais servent à masquer des signes dans des chaînes de caractères.
Comme pour les références de scalaires. Perl vous propose aussi différentes possibilités de notation. Ainsi vous pouvez également noter @$pointeur_phrases
au lieu de @{$pointeur_phrases}
et au lieu de $pointeur_phrases->[2]
vous pouvez également noter la variante "des origines" ${$pointeur_phrases}[2]
ou bien employer la variante $$pointeur_phrases[2]
.
Vous pouvez créer un pointeur sur un Hash et accéder par cette référence au hash en tant que tout ainsi qu'à ses clés et valeurs.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); my %langages = ( HTML => "How To Make Love. ", XHTML => "Extended How To Make Love. ", XML => "Extended Making Love. " ); my $pointeur_langages = \%langages; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "Type de variable et adresse mémoire de %langages: $pointeur_langages<br>\n"; print "Contenu de %langages: ", %{$pointeur_langages}," <br>\n"; print "Signification de XML: $pointeur_langages->{XML} <br>\n"; print "</body></html>\n"; |
Dans l'exemple est d'abord déclaré un hash nommé %langages
qui est initialisé avec des valeurs de départ. Ensuite est déclarée une référence à ce hash nommée $pointeur_langages
. La référence elle même est une scalaire, qui devient référence par la valeur \%langages
qui lui est affectée. La barre oblique inversée devant le signe pourcentage signale la référence au hash.
Le script en exemple envoie du code HTML au navigateur appelant et sort ici différentes données. Dans la première instruction print
est sortie pour une meilleure compréhension, la valeur sauvegardée de la référence $pointeur_langages
- il s'agit de quelque chose comme HASH(0xb65b28)
.
La deuxième instruction print
sort le contenu complet du hash. Il est accédé au hash, comme un tout par la référence avec la syntaxe %{$pointeur_langages}
. La référence figure donc dans des parenthèses accolades précédée immédiatement d'un signe "chez" @
qui désigne le hash.
Dans la troisième instruction print
l'élément du hash est adressé directement avec la clé XML
. Noté directement, cet élément pourrait être adressé avec $langages{XML}
. Dans l'exemple cependant, il est adressé par la référence et la syntaxe pour le faire est $pointeur_langages->{XML}
. La référence est donc notée suivie de l'opérateur flèche ->
et de la clé du hash souhaitée entre parenthèses accolades. à l'intérieur de $pointeur_langages->{XML}
aucun espace ne peut être placé dans ce contexte (donc à l'intérieur de chaînes de caractères).
Comme pour les références de tableaux, Perl vous propose aussi différentes possibilités de notation. Ainsi vous pouvez également noter %$pointeur_langages
au lieu de %{$pointeur_langages}
, et au lieu de $pointeur_langages->{XML}
vous pouvez également employer les variantes ${$pointeur_langages}{XML}
ou bien $$pointeur_langages{XML}
.
Vous pouvez fixer une référence à un sous-programme et appeler le sous-programme par cette référence.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); sub valeur_hasard { return int(rand(1000) + 1); } my $resultat = valeur_hasard(); my $pointeur_sousprogramme = \&valeur_hasard; my $Referenzergebnis = &{$pointeur_sousprogramme}(); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "Résultat: $resultat<br>\n"; print "Pointeur sur le sousprogramme: $pointeur_sousprogramme<br>\n"; print "Résultat de la référence: $resultat_reference<br>\n"; print "</body></html>\n"; |
Dans l'exemple est noté un sous-programme nommé valeur_hasard
. Ce sous-programme recherche à l'aide des fonctions Perl rand et int un nombre aléatoire entre 1 et 1000 et retourne le nombre trouvé avec return .
Avec l'instruction my $resultat = &valeur_hasard();
le sous-programme est appelé. La valeur renvoyée, donc le nombre aléatoire trouvé, est sauvegardé dans la scalaire resultat
.
Avec l'instruction my $pointeur_sousprogramme = \&valeur_hasard;
n'est déclarée par contre qu'une référence au sous-programme valeur_hasard
. La fonction n'en est pas pour autant appelée! La syntaxe \&valeur_hasard
lors de l'affectation de valeur fait en sorte qu'il s'agisse d'une référence. La barre oblique inversée signale la référence et le "ET" commercial &
un sous-programme. Derrière suit le nom du sous-programme.
Avec l'instruction my $resultat_reference = &{$pointeur_sousprogramme}();
le sous-programme valeur_hasard
est à nouveau appelé. Cette fois cependant pas directement comme dans la première instruction mais par la référence définie auparavant. La syntaxe est telle ici que la référence figure entre parenthèses accolades et qu'elle est précédés du "ET" commercial &
.
Les parenthèses normales vides derrière le nom ne sont pas absolument nécessaires. La valeur renvoyée par le deuxième appel de valeur_hasard
est sauvegardée dans la scalaire $resultat_reference
.
Le script en exemple envoie du code HTML au navigateur appelant en sortant les trois valeurs de $resultat
, $pointeur_sousprogramme
et $resultat_reference
. Tandis que les deux scalaires $resultat
et $resultat_reference
contiennent un nombre aléatoire entre 1 et 1000, le contenu de $pointeur_sousprogramme
n'est que le type de pointeur et l'adresse mémoire, par exemple quelque chose comme CODE(0xb65b28)
.
Perl vous offre aussi pour déréférencer les références de code différentes possibilités de notation. Ainsi vous pouvez, de façon analogue aux références de scalaires et de tableaux noter également &$pointeur_sousprogramme()
ou bien $pointeur_sousprogramme->()
au lieu de &{$pointeur_sousprogramme}()
.
Avec les Fonctions pour l'entrée/sortie et pour la lecture/écriture de données Perl vous avez beaucoup à faire avec les descripteurs de fichier. Les descripteurs de fichier ne se comportent pas autrement que des variables ordinaires. Ainsi vous ne pouvez pas leur affecter de valeur directe, mais seulement utiliser les valeurs affectées par l'interpréteur Perl lui-même, en cas de besoin au descripteur de fichier. Les valeurs contiennent des informations internes à Perl sur le canal d'entrée/sortie, et auxquelles vous accédez par le descripteur de fichier. Pour vous en tant qu'utilisateur, seul est intéressant le nom du descripteur, et l'interpréteur Perl s'occupe lui-même du reste.
Vous pouvez de la même façon poser une référence à un tel descripteur de fichier. Il y a ici une autre particularité par rapport aux variables habituelles en Perl: Vous n'avez pas besoin pour utiliser ce descripteur de fichier de déréférencer explicitement cette référence. Cela est réglé par l'interpréteur Perl automatiquement quand c'est nécessaire.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); open(FICHIER, "</tmp/server.cfg") || die "pas trouvé"; my $reference_descripteur = \*FICHIER; my @lignes = <$reference_descripteur>; my $nombre_lignes = @lignes; my $nom_descripteur = *{$reference_descripteur}; close($reference_descripteur); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "Lignes lues: $nombre_lignes<br>\n"; print "$reference_descripteur<br>\n"; print "$nom_descripteur<br>\n"; print "</body></html>\n"; |
L'exemple ouvre un fichier avec la fonction Perl open. Ici FICHIER
est le nom pour le descripteur de fichier par lequel il est accédé au fichier. Ce nom peut être choisi librement dans le cadre des règles pour l'attribution de noms, cependant vous ne devez pas par convention utiliser de minuscules. Quand vous utilisez l' option w de l'interpréteur Perl, vous recevez un avertissement quand le nom est mal choisi. Normalement le contenu du fichier pourrait être lu avec une instruction telle que my @lignes = <FICHIER>;
. Dan l'exemple ci-dessus cependant la lecture est effectuée indirectement par une référence.
Avec l'instruction my $reference_descripteur = \*FICHIER;
un pointeur sur le nom FICHIER
est déclaré (ou plutôt sur l'enregistrement dans le tableau des symboles internes à Perl). La barre oblique inversée au début de l'affectation indique la référence et l'astérisque *
un enregistrement dans le tableau des symboles (ce qu'on appelle un Typeglob). Derrière suit le nom du descripteur.
Avec my @lignes = <$reference_descripteur>;
le contenu du fichier peut maintenant être lu par la référence au descripteur de fichier. Au lieu de <FICHIER>
est donc simplement noté <$reference_descripteur>
. La référence au descripteur est résolue par l'interpréteur Perl lui-même.
L'instruction my $nombre_lignes = @lignes;
ne recherche simplement que le nombre de lignes pour une sortie de contrôle ultérieure.
Dans l'instruction my $nom_descripteur = *{$reference_descripteur};
la référence au descripteur de fichier est déréférencée encore une fois explicitement. Dans cette notation, donc dans les parenthèses accolades et avec l'astérisque qui précède, le nom du descripteur sauvegardé dans $reference_descripteur
est recherché, dans l'exemple il s'agit donc de FICHIER
. Ce faisant, l'espace de nommage actuel (package) est bien sûr également trouvé (voir aussi à ce sujet la fonction Perl package). La valeur effectivement trouvée dans l'exemple ci-dessus est *main::FICHIER
. Ici main
est simplement l'espace de nommage par défaut de Perl quand - comme dans l'exemple également ici - aucun autre espace de nommage n'a été mentionné. main::FICHIER
est désigné comme nom pleinement qualifié , étant donné qu'il exprime exactement dans quel espace de nommage peut être trouvé FICHIER
.
Le script en exemple envoie du code HTML au navigateur appelant et sort les valeurs trouvées. La valeur de $reference_descripteur
est quelque chose comme GLOB(0xb67968)
où GLOB
figure pour le type de référence "Typeglob".
De prime abord, travailler avec des références à des références peut paraître un pur exercice de style théorique. Il peut s'avérer tout à fait judicieux cependant pour des structures de données complexes de mettre en œuvre de telles références. Pour l'accès à des données distinctes d'une telle structure de données complexe justement, Perl atteint dans la notation une beauté assurément classique.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); my $maison = "maison particulière préfabriquée"; my @voitures = ("Citrë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 $Zeiger = \%pointeur_hash; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "(1.) $pointeur->{pointeur_maison}<br>\n"; print "(2.) ${$pointeur->{pointeur_maison}}<br>\n"; print "(3.) $pointeur->{pointeur_voiture}<br>\n"; print "(4.) @{$pointeur->{pointeur_voiture}}<br>\n"; print "(5.) $pointeur->{pointeur_voiture}->[2]<br>\n"; print "(6.) $pointeur->{pointeur_voiture}[3]<br>\n"; print "(7.) $pointeur->{pointeur_famille}<br>\n"; print "(8.)", %{$pointeur->{pointeur_famille}},"<br>\n"; print "(9.) $pointeur->{pointeur_famille}->{femme}<br>\n"; print "(10.) $pointeur->{pointeur_famille}{fils}<br>\n"; print "</body></html>\n"; |
L'exemple déclare tout d'abord une scalaire $maison
, un tableau @voitures
et un hash %famille
. Ensuite, des pointeurs ou références à ces variables sont définies. Étant donné cependant qu'il s'agit d'une série de pointeurs, ils ne sont pas déclarés séparément comme scalaires mais dans un hash nommé %pointeur_hash
. Chaque élément d'un hash ou d'une liste peut certes sauvegarder une scalaire et, étant donné que les références sont des scalaires, il n'y a aucun problème à créer des hashes ou des listes de références. Le hash de l'exemple contient par exemple comme affectation une clé nommée pointeur_maison
, avec laquelle une référence à la scalaire maison
est liée, ce qu'on peut voir à la barre oblique qui précède \$maison
. Il en va de même pour les autres références dans le hash.
Maintenant, on pourrait bien accéder par la variable hash %pointeur_hash
au références et à leurs valeurs. Dans l'exemple pourtant est encore déclarée une scalaire nommée $pointeur
, qui est une référence au hash %pointeur_hash
, ce qu'on peut voir à la notation \%pointeur_hash
pour l'affectation. $pointeur
est ainsi une référence au hash constitué de références.
L'exemple de script réunit ainsi toutes sortes de données et peut lors de la sortie de code HTML au navigateur envoyer les données les plus diverses. Pour la clarté, les sorties sont numérotées:
(1.) donne quelque chose comme: SCALAR(0xb65b7c)
, car $pointeur->{pointeur_maison}
équivaut à la valeur de l'élément hash avec la clé pointeur_maison
, qui est la référence à \$maison
.
(2.) sort: maison particulière préfabriquée
, car ${$pointeur->{pointeur_maison}}
équivaut à la valeur de l'élément hash avec la clé pointeur_maison
, donc la valeur de la référence \$maison
. Pour rechercher la valeur de la valeur, l'expression du (1.) est simplement placée encore une fois entre parenthèses accolades et précédée d'un signe dollar.
(3.) donne quelque chose comme: ARRAY(0xb65b4c)
, car $pointeur->{pointeur_voiture}
équivaut à la valeur de l'élément hash avec la clé pointeur_voiture
, et c'est la référence \@Auto
.
(4.) sort: Citrën Peugeot Renault Porsche
, car @{$pointeur->{pointeur_voiture}}
équivaut à la valeur de l'élément hash avec la clé pointeur_voiture
, donc en fin de compte la valeur de la référence \@voitures
, et c'est la liste complète @voitures
. Pour rechercher la valeur de la valeur, l'expression du (3.) est simplement placée encore une fois entre parenthèses accolades et précédée d'un signe "chez" @
.
(5.) sort: Renault
, car $pointeur->{pointeur_voiture}->[2]
équivaut à la valeur du troisième élément de la valeur de l'élément hash avec la clé pointeur_voiture
, donc finalement la troisième valeur de la référence \@voitures
, et il s'agit du troisième élément de @voitures
.
(6.) sort: Porsche
. C'est une notation abrégée pour le même résultat que pour (5.). Il suffit de noter le premier opérateur flèche ->
.
(7.) donne quelque chose comme: HASH(0xb65b58)
, car $pointeur->{pointeur_famille}
équivaut à la valeur de l'élément hash avec la clé pointeur_famille
, et c'est la référence \%famille
.
(8.) sort: filsFlorianfilleAnnefemmeFanny
, car %{$pointeur->{pointeur_famille}}
équivaut à la valeur de la valeur de l'élément hash avec la clé pointeur_famille
, donc en fin de compte la valeur de la référence \%famille
, et c'est le hash complet %famille
. Pour rechercher la valeur de la valeur, l'expression du (7.) est simplement placée encore une fois entre parenthèses accolades et précédée d'un signe pourcentage.
(9.) sort: Fanny
, car $pointeur->{pointeur_famille}->{femme}
équivaut à la valeur de l'élément hash avec le nom de clé femme
de la valeur de l'élément hash avec la clé pointeur_famille
.
(10.) sort: Florian
. C'est une notation abrégée pour le même résultat que pour (9.) et pour la même raison que pour (6.).
Variables prédéfinies en Perl | |
Hashes (Variables) | |
SELFHTML/Aides à la navigation CGI/Perl Éléments de langage Perl |
© 2001 Stefan Münz / © 2003 Traduction Serge François, 13405@free.fr
selfhtml@fr.selfhtml.org