Soru Perl'le benimki arasındaki fark nedir?


ne biliyorum my Perl'de. Yalnızca tanımlandığı blok kapsamında bulunan bir değişkeni tanımlar. Nedir our yap? Nasıl our farklı my?


170
2018-05-10 10:24


Menşei




Cevaplar:


Büyük soru: nasıl our farklı my ve ne yapar our yap?

Özetle:

Perl 5'ten beri mevcut, my bildirmek için bir yoldur:

  • paket dışı değişkenler
  • özel,
  • yeni,
  • küresel olmayan değişkenler,
  • herhangi bir paketten ayrı. Yani değişken yapamam şeklinde erişilebilir $package_name::variable.


Diğer yandan, our değişkenler:

  • paket değişkenleri ve böylece otomatik olarak
  • global değişkenler,
  • kesinlikle özel değil,
  • ne de mutlaka yenidirler; ve onlar
  • kutu paketin dışında (veya sözcük kapsamı) nitelikli ad alanı, olarak $package_name::variable.


İle bir değişken bildirme our bunları kullanmak için değişkenleri önceden tanımlamanıza olanak tanır use strict yazım hatası uyarıları veya derleme zamanı hataları almadan. Perl 5.6'dan beri, eski yerini almıştır. use vars, sadece dosya kapsamlıdır ve sözcük olarak açıklanamaz our.

Örneğin, değişken için resmi, nitelikli isim $x içeride package main olduğu $main::x. bildirilmesi our $x Çıplakı kullanmana izin verir $x Betimlemenin kapsamında, komut dosyası kullanıldığında, ceza olmadan değişken (yani, sonuçta meydana gelen bir hata olmadan) use strict veya use strict "vars". Kapsam bir, iki veya daha fazla paket veya küçük bir blok olabilir.


196
2018-05-20 02:22



Peki bizim yerelden nasıl farklılıklar gösteriyor? - Nathan Fellman
@Nathan Fellman, local değişkenler oluşturmaz. İle ilgili değil my ve our hiç local geçici olarak değişkenin değerini yedekler ve mevcut değerini temizler. - ikegami
our değişkenler paket değişkenleri değildir. Onlar global olarak kapsamı dışındalar, ancak sözcüksel olarak değişkenlik gösteren değişkenler my değişkenler. Bunu aşağıdaki programda görebilirsiniz: package Foo; our $x = 123; package Bar; say $x;. Bir paket değişkenini "bildirmek" istiyorsanız, kullanmanız gerekir use vars qw( $x );. our $x; paket içinde aynı adlı değişkene takma adı verilen sözcüksel olarak kapsam dışı bir değişken bildirir. our derlendi. - ikegami


Cartman ve Olafur'dan PerlMonks ve PerlDoc linkleri harika bir referanstır - aşağıda bir özetle benim çatlakım:

my değişkenler, tarafından tanımlanan tek bir blok içinde sözcüksel olarak kapsamlıdır {} ya da içinde değilse aynı dosya içinde {}s. Aynı sözcük kapsamı / bloğu dışında tanımlanan paketlerden / alt programlardan erişilemezler.

our değişkenler bir paket / dosya içinde kapsamlanır ve herhangi bir koddan erişilebilir use veya require Bu paket / dosya - ad çakışmaları, uygun ad alanı hazırlayarak paketler arasında çözülür.

Sadece yuvarlamak için local değişkenler "dinamik olarak" kapsamlıdır, my Aynı blok içinde çağrılan alt rutinlerden de erişilebilir oldukları için değişkenler.


58
2018-05-10 14:00



"İçin +1"my değişkenler, söz konusu dosyalar içinde değilse aynı dosya içinde sözcüksel olarak [...] belirtilir. {}"Bu benim için faydalı oldu, teşekkürler. - Georg


Bir örnek:

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";

45
2018-06-13 16:11



İyi cevap. Bir kereden fazla ifade edemem utanç verici. - Nathan Fellman
Yerine # 5, yorum okumalı # 2. - Roland Illig


Kapsam Belirleme ile Başa Çıkma Perl kapsam belirleme kurallarına genel bir bakış. Bu yeterince yaşlı our metnin gövdesinde tartışılmaz. İçinde ele alındı notlar sonunda bölüm.

Makale, paket değişkenleri ve dinamik kapsamdan ve bunların sözcüksel değişkenlerden ve sözcük kapsamından nasıl farklılaştığından bahsediyor.


12
2018-05-10 16:37





benim global değişkenler için kullanıldığı gibi yerel değişkenler için kullanılır. Daha fazla okuma Perl'de Değişken Kapsam Belirleme: Temeller .


6
2018-05-10 10:27



Yerel ve küresel kelimelerin etrafında durmaya dikkat edin. Uygun terimler sözlüksel ve pakettir. Perl'de gerçek global değişkenler yaratamazsınız, ancak bazıları zaten $ _ gibi olabilir ve yerel, yerel değişkenlerle (yerel tarafından oluşturulan), değişkenlere (benim ile oluşturulmuş) değil, paket değişkenlerine başvurur. - Chas. Owens
${^Potato} küreseldir. Kullandığınız yerden bağımsız olarak aynı değişkeni ifade eder. - MJD


Bu eski bir soru, ama Perl'deki sözlü bildirimlerle ilgili birtakım tuzaklarla karşılaştım, bu da bu soruyla da alakalıydı, bu yüzden özetimi buraya ekledim:

1. tanım veya beyan?

local $var = 42; 
print "var: $var\n"; 

Çıktı var: 42. Ancak, local $var = 42; bir tanım veya beyandır. Ama buna ne dersin?

use strict;
use warnings;

local $var = 42;
print "var: $var\n";

İkinci program bir hata verecek:

Global symbol "$var" requires explicit package name.

$var tanımlı değil, yani local $var; sadece bir beyanname! Kullanmadan önce local Bir değişken bildirmek için, daha önce bir genel değişken olarak tanımlandığından emin olun.

Ama bu neden başarısız olmaz?

use strict;
use warnings;

local $a = 42;
print "var: $a\n";

Çıktı: var: 42.

O yüzden $a, Hem de $b, Perl'de önceden tanımlanmış global bir değişkendir. Hatırla çeşit işlev?

2. sözlüksel veya global?

Perl kullanmaya başlamadan önce bir C programcısıydım, bu yüzden sözcüksel ve global değişkenler kavramı benim için basit görünüyor: C'deki otomatik ve harici değişkenlere karşılık geliyor. Fakat küçük farklılıklar var:

C'de, bir dış değişken herhangi bir fonksiyon bloğu dışında tanımlanmış bir değişkendir. Öte yandan, bir otomatik değişken, bir fonksiyon bloğu içinde tanımlanmış bir değişkendir. Bunun gibi:

int global;

int main(void) {
    int local;
}

Perl'deyken, işler ince:

sub main {
    $var = 42;
}

&main;

print "var: $var\n";

Çıktı var: 42, $var bir fonksiyon bloğunda tanımlanmış olsa bile global bir değişkendir! Aslında Perl'de, herhangi bir değişken varsayılan olarak global olarak beyan edilir.

Ders her zaman eklemek use strict; use warnings; Bir Perl programının başlangıcında, programcının sözel değişkenleri açık bir şekilde ilan etmesini zorlayacak, böylece verilen bazı hatalardan mahrum kalmayacağız.


4
2017-11-07 15:31



Daha fazla bilgi için ["[a ve b $ in] sıralamasında")stackoverflow.com/a/26128328/1028230). Perl, beni asla şaşırtmaz. - ruffin


perldoc Bizim iyi bir tanımımız var.

Her ikisi de bir değişken için depolamayı tahsis eden ve geçerli kapsamda kullanmak üzere bu depoya basit bir ad ekleyen benimkinden farklı olarak, iş ortaklarımız geçerli kapsamda kullanım için geçerli paketteki bir paket değişkeniyle basit bir ad. Başka bir deyişle, bizimkiyle aynı kapsam belirleme kurallarımız var, ama mutlaka bir değişken oluşturmuyor.


3
2018-05-10 10:25





Bu soruyla bir ilgisi var, ama "benim" (yerel) ile kullanamayacağınız "bizim" (paket) değişkenlerimizle kullanabileceğiniz bir (bana) belirsiz perl sözdizimini keşfettim. değişkenler.

#!/usr/bin/perl

our $foo = "BAR";

print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";

Çıktı:

BAR
BAZ

Eğer 'bizim' olanı 'benim' değiştirirseniz bu işe yaramaz.


2
2017-12-02 15:03



Öyle değil. $ foo $ {foo} $ {'foo'} $ {"foo"} hepsi değişken atamalar veya hata giderme için aynı şekilde çalışır. Takas bizim yukarıdaki örnekte benim çalışır. Muhtemelen deneyimlediğiniz şey, $ main :: foo veya $ :: foo gibi paket değişkenleri gibi paket değişkenleri için çalışacak paket değişkenleri olarak $ foo'yu denemeye çalışmaktı. bizim. - Cosmicnet
Sadece v5.20 kullanarak tekrar test edildi ve kesinlikle aynı çıktıyı benim ile vermiyor (BAR'ı iki kez basıyor.) - Misha Gale
Testim (pencerelerde): perl -e "my $foo = 'bar'; print $foo; ${foo} = 'baz'; pr int $foo" çıktı: barbaz  perl -e "my $foo = 'bar'; print $foo; ${"foo"} = 'baz'; print $foo" çıktı: barbaz  perl -e "my $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo" çıktı: barbar     Yani benim testimde aynı tuzağa düşecektim. $ {foo} $ foo ile aynıdır, parantezler enterpolasyon yaparken faydalıdır. $ {"foo"} aslında, ana kapsam tablosundaki $ {main = {} biçimindeki ana dizin tablosuna ait bir görünümdür. - Cosmicnet
$ {"main :: foo"}, $ {":: foo"} ve $ main :: foo, $ {"foo"} ile aynıdır. Shorthand paket duyarlı perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo" Çalışmalar, bu bağlamda $ {"foo"} şimdi $ {"test :: foo"} 'ya eşittir. Sembol Tabloları ve Glob Gelişmiş Perl programlama kitabı gibi bazı bilgileri vardır. Önceki hatam için üzgünüm. - Cosmicnet