my#
Δηλώνει μία ή περισσότερες μεταβλητές με λεξιλογική εμβέλεια.
my introduces new variables whose visibility is bounded by the enclosing block, file, or eval. The compiler records the declaration at compile time; the storage is allocated and (re)initialised each time control enters the scope. Unlike local, my does not temporarily replace a package variable
it creates a genuinely new variable that exists only while the scope is live and is invisible outside it, including to any subroutines the scope calls.
Σύνοψη#
my EXPR
my TYPE EXPR
my EXPR : ATTRS
my TYPE EXPR : ATTRS
Μία μεταβλητή μπορεί να γραφεί χωρίς παρενθέσεις· λίστα δύο ή περισσότερων πρέπει να είναι σε παρενθέσεις:
my $x;
my ($a, $b, @rest);
my Foo $obj;
my $x : shared = 0;
Τι επιστρέφεται#
Η my είναι δήλωση, όχι τελεστής παραγωγής τιμής με τη συνηθισμένη έννοια. Σε θέση rvalue αποδίδει τη μεταβλητή της (ή τη λίστα μεταβλητών) ως lvalue στο οποίο μπορείτε να αναθέσετε. Οι συνήθεις ιδιωματισμοί είναι:
my $x = $expr; # scalar context on RHS
my ($first, @rest) = @list; # list context on RHS; destructuring
my @copy = @src; # list context; @copy gets the elements
my %h = @pairs; # list context; pairs populate the hash
Όταν δεν δίνεται αρχικοποιητής, κάθε δηλωμένη μεταβλητή ξεκινά ως undef (βαθμωτό), κενή λίστα (πίνακας) ή κενός hash.
Εμβέλεια και διάρκεια ζωής#
Εμβέλεια μπλοκ. Μια μεταβλητή
myείναι ορατή από το σημείο αμέσως μετά τη δήλωσή της μέχρι το τέλος του πιο εσωτερικού περικλείοντος μπλοκ, αρχείου,eval,do,requireή αρχείου που έχει φορτωθεί μεuse.Εμβέλεια ελεγκτικής έκφρασης. Η ελεγκτική έκφραση των
if/unless/elsif/else,while/until,for/foreachαποτελεί μέρος της εμβέλειας της δήλωσης που περιέχει. Στοwhile (my $line = <$fh>) { ... }η μεταβλητή$lineείναι ζωντανή σε όλο το σώμα του βρόχου και στο μπλοκcontinueτου, αλλά όχι πέρα από αυτά.Φρέσκος αποθηκευτικός χώρος σε κάθε είσοδο. Κάθε φορά που ο έλεγχος εισέρχεται εκ νέου στην εμβέλεια, η μεταβλητή δημιουργείται από την αρχή. Αυτή είναι η βασική διαφορά από την
state, η οποία διατηρεί την τιμή της μεταξύ εισόδων.Οι κλειστότητες (closures) συλλαμβάνουν αποθηκευτικό χώρο, όχι τιμές. Μια ανώνυμη υπορουτίνα που δημιουργείται μέσα στην εμβέλεια κρατά αυτό το συγκεκριμένο στιγμιότυπο της μεταβλητής ζωντανό όσο η υπορουτίνα είναι προσπελάσιμη.
sub make_counter {
my $n = 0;
return sub { ++$n }; # closes over this $n
}
my $c = make_counter();
$c->(); $c->(); # 1, 2
Μορφή λίστας και αποδόμηση#
Με παρενθέσεις, η my παρέχει περιβάλλον λίστας στη δεξιά πλευρά και αποδομεί το αποτέλεσμα:
my ($sec, $min, $hour) = localtime;
my ($head, @tail) = @list; # @tail absorbs the rest
my ($x, $y) = ($y, $x); # swap via list assignment
Χρησιμοποιήστε undef ως placeholder για να παρακάμψετε μια θέση:
my (undef, $min, $hour) = localtime; # discard seconds
Χωρίς παρενθέσεις, το my $foo αποτελεί δήλωση μίας μόνο μεταβλητής και ο τελεστής κόμματος εφαρμόζεται σε ό,τι ακολουθεί:
my $foo, $bar = 1; # WRONG: declares $foo only;
# $bar is the package variable
my ($foo, $bar) = (0, 1); # Right.
Παγίδες περιβάλλοντος#
Η my δεν αλλάζει τον τρόπο που αξιολογείται η δεξιά πλευρά - τροποποιεί μόνο τη μεταβλητή στα αριστερά. Ένα βαθμωτό my $foo επιβάλλει βαθμωτό περιβάλλον· ένα my (...) σε παρενθέσεις επιβάλλει περιβάλλον λίστας:
my $line = <$fh>; # scalar context: one line
my ($line) = <$fh>; # list context: first of a list
my @lines = <$fh>; # list context: all remaining lines
Το κλασικό λάθος είναι να γράφεται my ($foo) = <$fh> ενώ ζητούνταν μία γραμμή - οι παρενθέσεις ενεργοποιούν περιβάλλον λίστας και το filehandle επιστρέφει λίστα ενός στοιχείου· τυχαίνει η τιμή να είναι η πρώτη γραμμή, αλλά το περιβάλλον γύρω είναι λάθος για ό,τι ακολουθεί.
my έναντι local έναντι our έναντι state#
Τέσσερις δηλώσεις, τέσσερις διαφορετικές σημασίες:
my- εισάγει μια νέα λεξιλογική μεταβλητή. Δεν είναι ορατή στον καλούμενο κώδικα. Φρέσκος αποθηκευτικός χώρος σε κάθε είσοδο.local- δεν δηλώνει τίποτα. Αποθηκεύει την τρέχουσα τιμή μιας υπάρχουσας μεταβλητής πακέτου και την επαναφέρει όταν η περικλείουσα εμβέλεια τερματίζει. Ορατή στον καλούμενο κώδικα μέσω δυναμικής εμβέλειας. Χρησιμοποιήστε την για τη μικρή χούφτα μαγικών καθολικών ($_,$/,$\,$,,$|,%ENV, …) που δεν μπορούν να γίνουν λεξιλογικές.our- δηλώνει ένα λεξιλογικό ψευδώνυμο για μια μεταβλητή πακέτου (καθολική). Ο αποθηκευτικός χώρος βρίσκεται στον πίνακα συμβόλων του πακέτου· ηourαπλώς σας επιτρέπει να την αναφέρετε χωρίς το πρόθεμα πακέτου για το υπόλοιπο της λεξιλογικής εμβέλειας. Ικανοποιεί τοuse strict 'vars'.state- όπως ηmyως προς την ορατότητα, αλλά ο αποθηκευτικός χώρος διατηρείται μεταξύ επανεισόδων στην εμβέλεια. Η αρχικοποίηση εκτελείται μία φορά· οι επόμενες είσοδοι αφήνουν την τιμή ανέπαφη.
package Counter;
our $total = 0; # package global; $Counter::total
my $cache; # lexical; invisible outside this file
state $calls = 0; # lexical; keeps its value across calls
sub tick {
local $\ = "\n"; # temporarily override output separator
++$calls;
print ++$total;
}
Κρίσιμο σημείο: η my $var δεν καλύπτει μια μεταβλητή πακέτου με το ίδιο όνομα. Η μεταβλητή πακέτου παραμένει προσβάσιμη μέσω της πλήρως ειδικευμένης μορφής της όσο η λεξιλογική είναι εντός εμβέλειας:
package main;
our $x = 10;
my $x = 20;
print "$x and $::x\n"; # "20 and 10\n"
TYPE και χαρακτηριστικά#
Και οι δύο μορφές αποτελούν μέρος της γλώσσας αλλά η σημασιολογία τους εξακολουθεί να εξελίσσεται (διατύπωση upstream).
TYPE - ένα bareword όνομα κλάσης, μια σταθερά δηλωμένη μέσω
use constant, ή το__PACKAGE__. Ιστορικά συνδεδεμένο με την pragmafields· για συνηθισμένη χρήση λειτουργεί ως υπόδειξη και δεν επιβάλλει τύπο κατά τον χρόνο εκτέλεσης.my Foo $obj = Foo->new;
ATTRS - μια λίστα χαρακτηριστικών εισαγόμενη με άνω-κάτω τελεία που χειρίζεται η pragma
attributes(και τοAttribute::Handlersαπό την 5.8.0).my $x : shared; my @buf : Locked;
Δείτε L<perlsub/»Private Variables via my()»> στο upstream για την έγκυρη διατύπωση.
Η δήλωση δεν είναι ακόμη εντός εμβέλειας στο ίδιο της το RHS#
Η νεοδηλωμένη μεταβλητή δεν είναι ορατή παρά μετά την ολοκλήρωση της εντολής δήλωσης. Αυτό κάνει αυτόν τον ιδιωματισμό καλά ορισμένο:
my $x = $x; # new $x initialised from the old $x
και αυτή τη συνθήκη εξαρτημένη από προϋπάρχον εξωτερικό $x:
my $x = 123 and $x == 123; # false unless the old $x was 123
Μέσα σε μία εντολή, οποιεσδήποτε περαιτέρω αναφορές στο όνομα παραπέμπουν στη σύνδεση προ της δήλωσης (ή προκαλούν σφάλμα strict 'vars' αν δεν υπάρχει τέτοια σύνδεση):
our $x = 2;
foo($x, my $x = $x + 1, $x); # foo() receives (2, 3, 2)
Παραδείγματα#
Τυπική είσοδος υπορουτίνας - ονομάστε τα ορίσματα:
sub distance {
my ($x1, $y1, $x2, $y2) = @_;
return sqrt( ($x2-$x1)**2 + ($y2-$y1)**2 );
}
Τοπικός δείκτης βρόχου με for my:
for my $i (1 .. 10) {
# $i is fresh each iteration; invisible after the loop
}
Ιδιωτική κατάσταση εμβέλειας αρχείου - η μεταβλητή υπάρχει για όλη τη ζωή του διερμηνέα αλλά δεν είναι προσπελάσιμη από έξω από αυτό το αρχείο:
my $cache = {};
sub lookup { $cache->{ $_[0] } //= _compute($_[0]) }
Ιδιωτική υπορουτίνα μέσω λεξιλογικής αναφοράς κώδικα:
my $helper = sub { ... };
$helper->($x);
Προειδοποίηση επισκίασης - η εκ νέου δήλωση στην ίδια εμβέλεια εκπέμπει προειδοποίηση κατηγορίας shadow υπό το use warnings:
use warnings 'shadow';
my $x = 1;
my $x = 2; # warning: "my" variable $x masks ...
Οριακές περιπτώσεις#
Μόνο αλφαριθμητικοί προσδιοριστές. Μαγικές ενσωματωμένες μεταβλητές όπως οι
$/,$_,$\,%ENV,@ARGVδεν μπορούν να γίνουν λεξιλογικές. Χρησιμοποιήστεlocalγια να τις θέσετε δυναμικά σε εμβέλεια.Καμία ειδίκευση πακέτου. Το
my $Foo::barείναι συντακτικό σφάλμα: οι μεταβλητέςmyδεν ανήκουν σε πακέτο και δεν μπορούν να φέρουν ειδικευτή::.Παρενθέσεις που λείπουν γύρω από λίστα. Το
my $a, $bδηλώνει μόνο το$a· το$bείναι η μεταβλητή πακέτου. Πάντα να βάζετε σε παρενθέσεις δύο ή περισσότερα ονόματα.Έκπληξη περιβάλλοντος λίστας. Το
my ($line) = <$fh>επιβάλλει περιβάλλον λίστας στην ανάγνωση· το RHS είναι λίστα ενός στοιχείου, όχι βαθμωτό. Αφαιρέστε τις παρενθέσεις αν θέλετε βαθμωτή σημασιολογία.foreachχωρίςmy. Τοfor $i (...)τοπικοποιεί το$iδυναμικά κατά τον τρόπο τηςlocal. Προτιμήστεfor my $i (...)για να περιορίσετε τον δείκτη λεξιλογικά.Επισκίαση σε βρόχους. Μια
myμέσα σε σώμα βρόχου δηλώνει φρέσκια μεταβλητή σε κάθε επανάληψη. Αν αυτό δεν είναι επιθυμητό (π.χ. μετρητής που πρέπει να επιβιώσει μεταξύ επαναλήψεων), δηλώστε την έξω από τον βρόχο ή χρησιμοποιήστεstate.Σύλληψη κλειστότητας. Μια κλειστότητα πάνω σε μια μεταβλητή
myκρατά εκείνο το συγκεκριμένο στιγμιότυπο ζωντανό. Διαφορετικές κλήσεις μιας περικλείουσας υπορουτίνας παράγουν ανεξάρτητες κλειστότητες πάνω σε ανεξάρτητες μεταβλητές.Αλληλεπίδραση με
use strict 'vars'. Ηmyικανοποιεί το strict-vars εντός της εμβέλειάς της· μεταβλητές χωρίς δήλωση πρέπει να είναιour, πλήρως ειδικευμένες, ή προδηλωμένες μεuse vars.Χρόνος μεταγλώττισης έναντι χρόνου εκτέλεσης. Η σύνδεση του ονόματος συμβαίνει κατά τη μεταγλώττιση· ο αρχικοποιητής εκτελείται κατά τον χρόνο εκτέλεσης, και επανεκτελείται σε κάθε είσοδο στην εμβέλεια. Δαπανηροί αρχικοποιητές μέσα σε καυτούς βρόχους πληρώνουν αυτό το κόστος σε κάθε επανάληψη.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
our- λεξιλογικό ψευδώνυμο για μεταβλητή πακέτου· ικανοποιεί τοstrict 'vars'χωρίς να δημιουργεί νέο αποθηκευτικό χώροlocal- δυναμικά οριοθετημένη αποθήκευση/επαναφορά υπάρχουσας μεταβλητής πακέτου· το εργαλείο για μαγικές καθολικέςstate- λεξιλογική όπως ηmy, αλλά ο αποθηκευτικός χώρος διατηρείται μεταξύ επανεισόδων στην εμβέλειαundef- placeholder σε λίσταmyμε παρενθέσεις, και η αρχική τιμή ενός μη αρχικοποιημένου βαθμωτούuse strict- κάνει ταmy/our/ πλήρως ειδικευμένα ονόματα υποχρεωτικά, εντοπίζοντας τυχαίες καθολικέςattributes- pragma που ερμηνεύει το τμήμα: ATTRSμιας δήλωσηςmy