Εμβέλεια

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__. Ιστορικά συνδεδεμένο με την pragma fields· για συνηθισμένη χρήση λειτουργεί ως υπόδειξη και δεν επιβάλλει τύπο κατά τον χρόνο εκτέλεσης.

    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