Je sais ce que my
en Perl. Il définit une variable qui n’existe que dans la scope du bloc dans lequel elle est définie. Qu’est-ce que our
faisons? Comment diffère-t-il de my
?
Bonne question: en quoi our
diffère-t-il de my
et de ce que our
faisons?
En résumé:
Disponible depuis Perl 5, my
est un moyen de déclarer:
$package_name::variable
. Par contre, our
variables sont:
$package_name::variable
. Déclarer une variable avec our
permet de prédéclarer des variables afin de les utiliser sous use ssortingct
sans avoir à recevoir d’avertissement typographique ni d’erreur de compilation. Depuis Perl 5.6, il a remplacé les use vars
obsolètes, qui use vars
qu’une scope de fichier et qui n’avaient pas de scope lexicale.
Par exemple, le nom qualifié formel de la variable $x
dans le package main
est $main::x
. Déclarer our $x
vous permet d’utiliser la variable bare $x
sans pénalité (c’est-à-dire sans erreur résultante), dans la scope de la déclaration, lorsque le script utilise l’ use ssortingct
ou use ssortingct "vars"
. La scope peut être un, deux ou plusieurs packages ou un petit bloc.
Les liens PerlMonks et PerlDoc de cartman et Olafur sont une excellente référence – ci-dessous est ma fissure à un résumé:
my
variables ont une scope lexicale dans un seul bloc défini par {}
ou dans le même fichier si ce n’est pas dans {}
s. Ils ne sont pas accessibles depuis les packages / sous-routines définis en dehors du même champ / bloc lexical.
our
variables sont définies dans un package / fichier et accessibles à partir de tout code use
ou require
que les conflits de nom de package / fichier soient résolus entre les packages en ajoutant au préalable l’espace de noms approprié.
Pour compléter, local
variables local
sont “dynamicment” définies, différant de my
variables, car elles sont également accessibles à partir de sous-routines appelées dans le même bloc.
Un exemple:
use ssortingct; for (1 .. 2){ # Both variables are lexically scoped to the block. our ($o); # Belongs to 'main' package. my ($m); # Does not belong to a package. # The variables differ with respect to newness. $o ++; $m ++; print __PACKAGE__, " >> o=$om=$m\n"; # $m is always 1. # The package has changed, but we still have direct, # unqualified access to both variables, because the # lexical scope has not changed. package Fubb; print __PACKAGE__, " >> o=$om=$m\n"; } # The our() and my() variables differ with respect to privacy. # We can still access the variable declared with our(), provided # that we fully qualify its name, but the variable declared # with my() is unavailable. print __PACKAGE__, " >> main::o=$main::o\n"; # 2 print __PACKAGE__, " >> main::m=$main::m\n"; # Undefined. # Attempts to access the variables directly won't comstack. # print __PACKAGE__, " >> o=$o\n"; # print __PACKAGE__, " >> m=$m\n"; # Variables declared with use vars() are like those declared # with our(): belong to a package; not private; and not new. # However, their scoping is package-based rather than lexical. for (1 .. 9){ use vars qw($uv); $uv ++; } # Even though we are outside the lexical scope where the # use vars() variable was declared, we have direct access # because the package has not changed. print __PACKAGE__, " >> uv=$uv\n"; # And we can access it from another package. package Bubb; print __PACKAGE__, " >> main::uv=$main::uv\n";
Faire face à la scope est un bon aperçu des règles de scope Perl. C’est assez vieux pour que our
ne soit pas discuté dans le corps du texte. Il est abordé dans la section Notes à la fin.
L’article parle des variables de package et de la scope dynamic et de la manière dont elles diffèrent des variables lexicales et de la scope lexicale.
mon est utilisé pour les variables locales, où notre est utilisé pour les variables globales. Plus de lecture sur la scope variable dans Perl: les bases .
C’est une vieille question, mais j’ai déjà rencontré des pièges à propos des déclarations lexicales dans Perl qui m’ont gêné, qui sont également liées à cette question, alors je viens d’append mon résumé ici:
1. définition ou déclaration?
local $var = 42; print "var: $var\n";
Le résultat est var: 42
. Cependant, nous ne pouvions pas dire si local $var = 42;
est une définition ou une déclaration. Mais qu’en est-il de cela:
use ssortingct; use warnings; local $var = 42; print "var: $var\n";
Le deuxième programme lancera une erreur:
Global symbol "$var" requires explicit package name.
$var
n’est pas défini, ce qui signifie local $var;
est juste une déclaration! Avant d’utiliser local
pour déclarer une variable, assurez-vous qu’elle est déjà définie en tant que variable globale.
Mais pourquoi cela ne va pas échouer?
use ssortingct; use warnings; local $a = 42; print "var: $a\n";
La sortie est la suivante: var: 42
.
C’est parce que $a
, tout comme $b
, est une variable globale prédéfinie en Perl. Rappelez-vous la fonction de sorting ?
2. lexical ou global?
J’étais un programmeur C avant de commencer à utiliser Perl, donc le concept de variables lexicales et globales me semble simple: correspond simplement aux variables auto et externes en C. Mais il y a de petites différences:
En C, une variable externe est une variable définie en dehors de tout bloc fonction. En revanche, une variable automatique est une variable définie dans un bloc fonction. Comme ça:
int global; int main(void) { int local; }
En Perl, les choses sont subtiles:
sub main { $var = 42; } &main; print "var: $var\n";
La sortie est var: 42
, $var
est une variable globale même si elle est définie dans un bloc fonction! En réalité, dans Perl, toute variable est déclarée comme globale par défaut.
La leçon est de toujours use ssortingct; use warnings;
use ssortingct; use warnings;
au début d’un programme Perl, ce qui obligera le programmeur à déclarer explicitement la variable lexicale, afin que nous ne soyons pas dérangés par certaines erreurs sockets pour acquises.
Le perldoc a une bonne définition de notre.
Contrairement à mon, qui alloue à la fois un stockage pour une variable et associe un nom simple à ce stockage pour l’utiliser dans la scope actuelle, notre associe un nom simple à une variable de package dans le package en cours, à utiliser dans l’étendue actuelle. En d’autres termes, notre règle de scope est la même que la mienne, mais ne crée pas nécessairement une variable.
Ceci est seulement un peu lié à la question, mais je viens de découvrir un bit de syntaxe Perl obscure que vous pouvez utiliser avec “nos” variables (package) que vous ne pouvez pas utiliser avec “my” (local) variables.
#!/usr/bin/perl our $foo = "BAR"; print $foo . "\n"; ${"foo"} = "BAZ"; print $foo . "\n";
Sortie:
BAR BAZ
Cela ne fonctionnera pas si vous changez “notre” en “mon”.
print "package is: " . __PACKAGE__ . "\n"; our $test = 1; print "trying to print global var from main package: $test\n"; package Changed; { my $test = 10; my $test1 = 11; print "trying to print local vars from a closed block: $test, $test1\n"; } &Check_global; sub Check_global { print "trying to print global var from a function: $test\n"; } print "package is: " . __PACKAGE__ . "\n"; print "trying to print global var outside the func and from \"Changed\" package: $test\n"; print "trying to print local var outside the block $test1\n";
Va sortir ceci:
package is: main trying to print global var from main package: 1 trying to print local vars from a closed block: 10, 11 trying to print global var from a function: 1 package is: Changed trying to print global var outside the func and from "Changed" package: 1 trying to print local var outside the block
Si vous utilisez “use ssortingct”, vous rencontrerez cet échec lors de la tentative d’exécution du script:
Global symbol "$test1" requires explicit package name at ./check_global.pl line 24. Execution of ./check_global.pl aborted due to compilation errors.
Essayez simplement d’utiliser le programme suivant:
#!/usr/local/bin/perl use feature ':5.10'; #use warnings; package a; { my $b = 100; our $a = 10; print "$a \n"; print "$b \n"; } package b; #my $b = 200; #our $a = 20 ; print "in package b value of my b $a::b \n"; print "in package b value of our a $a::a \n";
#!/usr/bin/perl -l use ssortingct; # if ssortingng below commented out, prints 'lol' , if the ssortingng enabled, prints 'eeeeeeeee' #my $lol = 'eeeeeeeeeee' ; # no errors or warnings at any case, despite of 'ssortingct' our $lol = eval {$lol} || 'lol' ; print $lol;
Pensons à ce qu’est réellement un interpréteur: c’est un morceau de code qui stocke les valeurs en mémoire et laisse les instructions dans un programme qu’il interprète accéder à ces valeurs par leurs noms, qui sont spécifiés dans ces instructions. Le grand travail d’un interprète consiste donc à définir les règles d’utilisation des noms dans ces instructions pour accéder aux valeurs stockées par l’interpréteur.
En rencontrant “my”, l’interpréteur crée une variable lexicale: une valeur nommée à laquelle l’interprète ne peut accéder que pendant l’exécution d’un bloc, et uniquement à partir de ce bloc syntaxique. En rencontrant “notre”, l’interpréteur crée un alias lexical d’une variable de package: il lie un nom, que l’interpréteur est censé traiter depuis le nom d’une variable lexicale, jusqu’à la fin du bloc, à la valeur du paquet variable avec le même nom.
L’effet est que vous pouvez alors prétendre que vous utilisez une variable lexicale et ignorer les règles d’utilisation ssortingcte sur la qualification complète des variables de package. Comme l’interpréteur crée automatiquement des variables de paquet lors de leur première utilisation, l’effet secondaire de “notre” peut également être que l’interpréteur crée également une variable de package. Dans ce cas, deux choses sont créées: une variable de package à laquelle l’interprète peut accéder de partout, à condition qu’elle soit correctement désignée comme demandé par «use ssortingct» (précédé du nom de son package et de deux points) et son alias lexical.
Sources: