Eu sei o que myhá em Perl. Ele define uma variável que existe apenas no escopo do bloco em que está definida. O que ourfaz?
Como é que ourdifere my?
Eu sei o que myhá em Perl. Ele define uma variável que existe apenas no escopo do bloco em que está definida. O que ourfaz?
Como é que ourdifere my?
Respostas:
Ótima pergunta: como ourdifere mye o que ourfaz?
Em suma:
Disponível desde o Perl 5, myé uma maneira de declarar variáveis que não são de pacote, que são:
$package_name::variable.Por outro lado, ourvariáveis são variáveis de pacote e, portanto, automaticamente:
$package_name::variable.Declarar uma variável com ourpermite pré-declarar variáveis para usá-las use strictsem receber avisos de erro de digitação ou erros em tempo de compilação. Desde o Perl 5.6, ele substituiu o obsoleto use vars, que tinha apenas escopo de arquivo e não lexicamente como está our.
Por exemplo, o nome formal e qualificado para a variável $xinside package mainé $main::x. Declarar our $xpermite que você use a $xvariável bare sem penalidade (ou seja, sem erro resultante), no escopo da declaração, quando o script usa use strictor use strict "vars". O escopo pode ser um ou dois ou mais pacotes ou um pequeno bloco.
localnão cria variáveis. Ele não se relaciona com mye ourem tudo. localfaz backup temporário do valor da variável e limpa seu valor atual.
ourvariáveis não são variáveis de pacote. Eles não têm escopo global, mas variáveis de escopo lexical como as myvariáveis. Você pode ver que o seguinte programa: package Foo; our $x = 123; package Bar; say $x;. Se você quiser "declarar" uma variável do pacote, precisará usar use vars qw( $x );. our $x;declara uma variável de escopo lexicamente alias à variável com o mesmo nome no pacote em que a ourcompilação foi compilada.
Os links PerlMonks e PerlDoc da cartman e Olafur são uma ótima referência - abaixo está minha rachadura em um resumo:
myas variáveis têm escopo lexicamente dentro de um único bloco definido por {}ou dentro do mesmo arquivo, se não em {}s. Eles não são acessíveis a partir de pacotes / sub-rotinas definidas fora do mesmo escopo / bloco lexical.
ouras variáveis têm o escopo definido dentro de um pacote / arquivo e acessíveis a partir de qualquer código que useou requireaquele conflito de nome do pacote / arquivo seja resolvido entre os pacotes, precedendo o espaço de nome apropriado.
Para finalizar, as localvariáveis têm escopo "dinâmico", diferindo das myvariáveis, pois também são acessíveis a partir de sub-rotinas chamadas dentro do mesmo bloco.
myvariáveis têm escopo lexicamente [...] dentro do mesmo arquivo, se não em {}s". Isso foi útil para mim, obrigado.
Um exemplo:
use strict;
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=$o m=$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=$o m=$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 compile.
# 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";
Lidar com o escopo é uma boa visão geral das regras de escopo do Perl. É velho o suficiente para ournão ser discutido no corpo do texto. É abordada na seção Notas no final.
O artigo fala sobre variáveis de pacote e escopo dinâmico e como isso difere de variáveis lexicais e escopo lexical.
myé usado para variáveis locais, enquanto que ouré usado para variáveis globais.
Leia mais em Variable Scoping in Perl: the basic .
${^Potato}é global. Refere-se à mesma variável, independentemente de onde você a usa.
Eu já conheci algumas armadilhas sobre declarações lexicais no Perl que me atrapalharam, que também estão relacionadas a essa pergunta, então apenas adiciono meu resumo aqui:
1. Definição ou declaração?
local $var = 42;
print "var: $var\n";
A saída é var: 42. No entanto, não sabemos se local $var = 42;é uma definição ou declaração. Mas e quanto a isso:
use strict;
use warnings;
local $var = 42;
print "var: $var\n";
O segundo programa lançará um erro:
Global symbol "$var" requires explicit package name.
$varnão está definido, o que significa que local $var;é apenas uma declaração! Antes de usar localpara declarar uma variável, verifique se ela está definida como uma variável global anteriormente.
Mas por que isso não irá falhar?
use strict;
use warnings;
local $a = 42;
print "var: $a\n";
A saída é: var: 42.
Isso porque $a, além de $b, é uma variável global predefinida no Perl. Lembre-se da função de classificação ?
2. Lexical ou global?
Eu era um programador C antes de começar a usar o Perl, então o conceito de variáveis lexicais e globais parece direto para mim: apenas corresponde a variáveis automáticas e externas em C. Mas há pequenas diferenças:
Em C, uma variável externa é uma variável definida fora de qualquer bloco de função. Por outro lado, uma variável automática é uma variável definida dentro de um bloco de funções. Como isso:
int global;
int main(void) {
int local;
}
Enquanto em Perl, as coisas são sutis:
sub main {
$var = 42;
}
&main;
print "var: $var\n";
A saída é var: 42. $varé uma variável global, mesmo que esteja definida em um bloco de funções! Na verdade, em Perl, qualquer variável é declarada como global por padrão.
A lição é sempre adicionar use strict; use warnings;no início de um programa Perl, o que forçará o programador a declarar explicitamente a variável lexical, para que não fiquemos confusos com alguns erros tomados como garantidos.
O perldoc tem uma boa definição de nossa.
Ao contrário de my, que aloca armazenamento para uma variável e associa um nome simples a esse armazenamento para uso no escopo atual, nosso associa um nome simples a uma variável de pacote no pacote atual, para uso dentro do escopo atual. Em outras palavras, nossa possui as mesmas regras de escopo que a minha, mas não cria necessariamente uma variável.
Isso está apenas um pouco relacionado à questão, mas eu acabei de descobrir um bit obscuro (para mim) de sintaxe perl que você pode usar com variáveis "our" (package) que você não pode usar com "my" (local) variáveis.
#!/usr/bin/perl
our $foo = "BAR";
print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";
Resultado:
BAR
BAZ
Isso não funcionará se você alterar 'nosso' para 'meu'.
perl -e "my $foo = 'bar'; print $foo; ${foo} = 'baz'; pr int $foo"output: barbaz perl -e "my $foo = 'bar'; print $foo; ${"foo"} = 'baz'; print $foo"output: barbaz perl -e "my $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"output: barbar Então, em meus testes, caí na mesma armadilha. $ {foo} é o mesmo que $ foo, os colchetes são úteis ao interpolar. $ {"foo"} é, na verdade, uma consulta a $ main :: {}, que é a tabela principal de símbolos, pois contém apenas variáveis com escopo definido no pacote.
perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo", pois neste contexto $ {"foo"} agora é igual a $ {"test :: foo"}. Of Symbol Tables and Globs tem algumas informações, assim como o livro de programação Advanced Perl. Desculpe pelo meu erro anterior.
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";
Saída isso:
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
No caso de usar "use strict", ocorrerá esta falha ao tentar executar o script:
Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.
Apenas tente usar o seguinte programa:
#!/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 strict;
# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'
our $lol = eval {$lol} || 'lol' ;
print $lol;
oure mydiferentes? Como este exemplo mostra isso?
Vamos pensar o que realmente é um intérprete: é um pedaço de código que armazena valores na memória e permite que as instruções em um programa que ele interpreta acessem esses valores por seus nomes, especificados nessas instruções. Portanto, o grande trabalho de um intérprete é moldar as regras de como devemos usar os nomes nessas instruções para acessar os valores que o intérprete armazena.
Ao encontrar "meu", o intérprete cria uma variável lexical: um valor nomeado que o intérprete pode acessar apenas enquanto executa um bloco e somente dentro desse bloco sintático. Ao encontrar "our", o intérprete cria um alias lexical de uma variável do pacote: vincula um nome, que o intérprete deve processar a partir de então como o nome de uma variável lexical, até o término do bloco, ao valor do pacote variável com o mesmo nome.
O efeito é que você pode fingir que está usando uma variável lexical e ignorar as regras de 'use strict' na qualificação completa das variáveis de pacote. Como o intérprete cria automaticamente variáveis de pacote quando elas são usadas pela primeira vez, o efeito colateral de usar "our" também pode ser que o intérprete crie também uma variável de pacote. Nesse caso, duas coisas são criadas: uma variável de pacote, que o intérprete pode acessar de qualquer lugar, desde que seja adequadamente designada conforme solicitado por 'use strict' (precedido com o nome de seu pacote e dois pontos) e seu alias lexical.
Fontes: