Saya tahu apa yang my
ada di Perl. Ini mendefinisikan variabel yang hanya ada dalam lingkup blok di mana ia didefinisikan. Apa yang our
harus dilakukan
Bagaimana our
berbeda dari my
?
Saya tahu apa yang my
ada di Perl. Ini mendefinisikan variabel yang hanya ada dalam lingkup blok di mana ia didefinisikan. Apa yang our
harus dilakukan
Bagaimana our
berbeda dari my
?
Jawaban:
Pertanyaan besar: Bagaimana our
berbeda dari my
dan apa yang our
lakukan?
Singkatnya:
Tersedia sejak Perl 5, my
adalah cara untuk mendeklarasikan variabel non-paket, yaitu:
$package_name::variable
.Di sisi lain, our
variabel adalah variabel paket, dan dengan demikian secara otomatis:
$package_name::variable
.Mendeklarasikan variabel dengan our
memungkinkan Anda untuk mendeklarasikan variabel untuk menggunakannya di bawah use strict
tanpa mendapat peringatan kesalahan ketik atau kesalahan waktu kompilasi. Sejak Perl 5.6, ia telah menggantikan yang sudah usang use vars
, yang hanya mencakup file, dan tidak dibatasi secara leksikal sepertiour
.
Misalnya, nama formal dan berkualitas untuk variabel $x
di dalamnya package main
adalah $main::x
. Deklarasi our $x
memungkinkan Anda untuk menggunakan $x
variabel kosong tanpa penalti (yaitu, tanpa kesalahan yang dihasilkan), dalam lingkup deklarasi, ketika skrip menggunakan use strict
atau use strict "vars"
. Lingkupnya mungkin satu, atau dua, atau lebih paket, atau satu blok kecil.
local
tidak membuat variabel. Itu tidak berhubungan dengan my
dan our
sama sekali. local
sementara mencadangkan nilai variabel dan menghapus nilai saat ini.
our
variabel bukan variabel paket. Mereka bukan lingkup global, tetapi variabel cakupannya leksikal seperti my
variabel. Anda dapat melihat bahwa dalam program berikut: package Foo; our $x = 123; package Bar; say $x;
. Jika Anda ingin "mendeklarasikan" variabel paket, Anda perlu menggunakannya use vars qw( $x );
. our $x;
mendeklarasikan variabel cakupan-leksikal yang alias ke variabel dengan nama yang sama dalam paket di mana our
dikompilasi.
Tautan PerlMonks dan PerlDoc dari cartman dan Olafur adalah referensi yang bagus - di bawah ini adalah ringkasan saya di ringkasan:
my
variabel dibatasi secara leksikal dalam satu blok yang ditentukan oleh {}
atau di dalam file yang sama jika tidak dalam {}
s. Mereka tidak dapat diakses dari paket / subrutin yang didefinisikan di luar lingkup / blok leksikal yang sama.
our
variabel dicakup dalam suatu paket / file dan dapat diakses dari kode apa pun use
atau require
bahwa paket / file - konflik nama diselesaikan di antara paket dengan menambahkan ruang nama yang sesuai.
Untuk mengatasinya, local
variabel dibatasi secara "dinamis", berbeda dengan my
variabel yang juga dapat diakses dari subrutin yang disebut dalam blok yang sama.
my
variabel dicakup secara leksikal [...] dalam file yang sama jika tidak dalam {}
s". Itu berguna bagi saya, terima kasih.
Sebuah contoh:
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";
Mengatasi Pelingkupan adalah gambaran umum yang baik dari aturan pelingkupan Perl. Sudah cukup tua yang our
tidak dibahas dalam isi teks. Itu dibahas di bagian Catatan di bagian akhir.
Artikel ini berbicara tentang variabel paket dan ruang lingkup dinamis dan bagaimana hal itu berbeda dari variabel leksikal dan ruang lingkup leksikal.
my
digunakan untuk variabel lokal, sedangkan our
digunakan untuk variabel global.
Lebih banyak membaca di Variabel Pelingkupan di Perl: dasar-dasarnya .
${^Potato}
bersifat global. Ini merujuk ke variabel yang sama di mana pun Anda menggunakannya.
Saya pernah bertemu beberapa jebakan tentang deklarasi leksikal di Perl yang mengacaukan saya, yang juga terkait dengan pertanyaan ini, jadi saya tambahkan saja ringkasan saya di sini:
1. Definisi atau deklarasi?
local $var = 42;
print "var: $var\n";
Outputnya adalah var: 42
. Namun kami tidak tahu apakah local $var = 42;
itu definisi atau deklarasi. Tapi bagaimana dengan ini:
use strict;
use warnings;
local $var = 42;
print "var: $var\n";
Program kedua akan menimbulkan kesalahan:
Global symbol "$var" requires explicit package name.
$var
tidak didefinisikan, yang berarti local $var;
hanya deklarasi! Sebelum menggunakan local
untuk mendeklarasikan variabel, pastikan bahwa itu didefinisikan sebagai variabel global sebelumnya.
Tetapi mengapa ini tidak akan gagal?
use strict;
use warnings;
local $a = 42;
print "var: $a\n";
Outputnya adalah: var: 42
.
Itu karena $a
, juga $b
, adalah variabel global yang telah ditentukan sebelumnya di Perl. Ingat fungsi sortir ?
2. Leksikal atau global?
Saya adalah seorang programmer C sebelum mulai menggunakan Perl, jadi konsep variabel leksikal dan global tampaknya langsung bagi saya: itu hanya sesuai dengan variabel otomatis dan eksternal dalam C. Tapi ada perbedaan kecil:
Dalam C, variabel eksternal adalah variabel yang didefinisikan di luar blok fungsi apa pun. Di sisi lain, variabel otomatis adalah variabel yang didefinisikan di dalam blok fungsi. Seperti ini:
int global;
int main(void) {
int local;
}
Sementara di Perl, semuanya halus:
sub main {
$var = 42;
}
&main;
print "var: $var\n";
Outputnya adalah var: 42
. $var
adalah variabel global bahkan jika itu didefinisikan dalam blok fungsi! Sebenarnya di Perl, variabel apa pun dinyatakan sebagai global secara default.
Pelajarannya adalah untuk selalu menambahkan use strict; use warnings;
di awal program Perl, yang akan memaksa programmer untuk mendeklarasikan variabel leksikal secara eksplisit, sehingga kita tidak menjadi kacau oleh beberapa kesalahan yang diterima begitu saja.
The perldoc memiliki definisi yang baik dari kami.
Tidak seperti saya, yang keduanya mengalokasikan penyimpanan untuk variabel dan mengaitkan nama sederhana dengan penyimpanan itu untuk digunakan dalam lingkup saat ini, kami mengaitkan nama sederhana dengan variabel paket dalam paket saat ini, untuk digunakan dalam lingkup saat ini. Dengan kata lain, kami memiliki aturan pelingkupan yang sama dengan saya, tetapi tidak harus membuat variabel.
Ini hanya agak terkait dengan pertanyaan, tetapi saya baru saja menemukan sedikit sintaks perl (bagi saya) yang tidak jelas yang dapat Anda gunakan dengan variabel "kami" (paket) yang tidak dapat Anda gunakan dengan "saya" (lokal) variabel.
#!/usr/bin/perl
our $foo = "BAR";
print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";
Keluaran:
BAR
BAZ
Ini tidak akan berhasil jika Anda mengubah 'kami' menjadi 'saya'.
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
Jadi dalam pengujian saya, saya jatuh ke dalam perangkap yang sama. $ {foo} sama dengan $ foo, tanda kurung berguna saat interpolasi. $ {"foo"} sebenarnya adalah tampilan hingga $ main :: {} yang merupakan tabel simbol utama, karena hanya berisi variabel scoped paket.
perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"
, karena dalam konteks ini $ {"foo"} sekarang sama dengan $ {"test :: foo"}. Tabel Simbol dan Glob memiliki beberapa informasi tentang itu, seperti halnya buku pemrograman Advanced Perl. Maaf atas kesalahan saya sebelumnya.
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";
Akan Keluarkan ini:
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
Jika menggunakan "gunakan ketat" akan mendapatkan kegagalan ini saat mencoba menjalankan skrip:
Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.
Coba gunakan program berikut:
#!/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;
our
dan my
berbeda? Bagaimana contoh ini menunjukkannya?
Mari kita pikirkan apa sebenarnya juru bahasa: itu adalah sepotong kode yang menyimpan nilai dalam memori dan membiarkan instruksi dalam program yang diinterpretasikan mengakses nilai-nilai tersebut dengan nama mereka, yang ditentukan di dalam instruksi ini. Jadi, pekerjaan besar seorang juru bahasa adalah untuk membentuk aturan bagaimana kita harus menggunakan nama-nama dalam instruksi tersebut untuk mengakses nilai-nilai yang disimpan oleh juru bahasa tersebut.
Saat menemukan "saya", interpreter menciptakan variabel leksikal: nilai bernama yang hanya dapat diakses oleh interpreter ketika mengeksekusi blok, dan hanya dari dalam blok sintaksis itu. Pada pertemuan "kita", penerjemah membuat alias leksikal dari variabel paket: ia mengikat nama, yang oleh penerjemah diharapkan sejak saat itu untuk diproses sebagai nama variabel leksikal, sampai blok selesai, dengan nilai paket variabel dengan nama yang sama.
Efeknya adalah bahwa Anda kemudian dapat berpura-pura bahwa Anda menggunakan variabel leksikal dan mengabaikan aturan 'gunakan ketat' pada kualifikasi penuh variabel paket. Karena penerjemah secara otomatis membuat variabel paket ketika mereka pertama kali digunakan, efek samping dari menggunakan "kami" juga mungkin bahwa penerjemah menciptakan variabel paket juga. Dalam hal ini, dua hal dibuat: variabel paket, yang dapat diakses oleh penerjemah dari mana-mana, asalkan ditunjuk dengan tepat seperti yang diminta oleh 'use strict' (diawali dengan nama paketnya dan dua titik dua), dan alias leksikalnya.
Sumber: