local#
Αποθηκεύει την τρέχουσα τιμή μιας μεταβλητής πακέτου και την επαναφέρει όταν η περικλείουσα εμβέλεια τερματίζεται.
Η local είναι ο τελεστής δυναμικής εμβέλειας. Δεν δηλώνει νέα μεταβλητή - απλώνεται σε μια υπάρχουσα μεταβλητή πακέτου (καθολική), αποθηκεύει την τρέχουσα τιμή σε μια κρυφή στοίβα διάσωσης και κανονίζει η αρχική τιμή να επαναφερθεί όταν ο έλεγχος εγκαταλείπει το τρέχον μπλοκ, την eval ή το do FILE. Οι καλούμενες υπορουτίνες βλέπουν την προσωρινή τιμή. Για τις περισσότερες ανάγκες τύπου «θέλω μια μεταβλητή τοπική σε αυτό το μπλοκ», το σωστό εργαλείο είναι η my· καταφύγετε στην local συγκεκριμένα όταν η μεταβλητή πρέπει να είναι καθολική σε επίπεδο πακέτου - οι μεταβλητές στίξης, τα filehandles ή εγγραφές στον πίνακα συμβόλων - και θέλετε αυτή η καθολική να έχει διαφορετική τιμή για τη διάρκεια ενός μπλοκ και κάθε υπορουτίνας που αυτό καλεί.
Σύνοψη#
local EXPR
local $var
local $var = EXPR
local (@list) = LIST
local $hash{key}
local $array[i]
local *GLOB
Τι επιστρέφεται#
Την τιμή της τοπικοποιημένης έκφρασης (τη νέα τιμή, μετά από οποιαδήποτε εκχώρηση στην ίδια εντολή). Η παρακολούθηση της στοίβας διάσωσης είναι παρενέργεια· η τιμή επιστροφής έχει σημασία μόνο όταν η local εμφανίζεται μέσα σε μεγαλύτερη έκφραση:
our $x = 2;
foo($x, local $x = $x + 1, $x); # foo() receives (2, 3, 3)
Δυναμική εμβέλεια, όχι λεξιλογική εμβέλεια#
Η local και η my είναι διαφορετικά είδη εμβέλειας:
Η
myδημιουργεί μια νέα, λεξιλογικά οριοθετημένη μεταβλητή. Μόνο κώδικας κειμενικά μέσα στο περικλείον μπλοκ μπορεί να τη δει. Οι καλούμενες υπορουτίνες όχι.Η
localδεν δημιουργεί τίποτα. Παρακάμπτει προσωρινά την τιμή μιας υπάρχουσας μεταβλητής πακέτου. Κάθε κομμάτι κώδικα - αυτό το μπλοκ και κάθε υπορουτίνα που καλεί, άμεσα ή μεταβατικά - βλέπει τη νέα τιμή μέχρι να τερματιστεί η εμβέλεια.
Γι” αυτόν τον λόγο η local είναι το σωστό εργαλείο για μεταβλητές στίξης όπως οι $/, $\, $,, $_ και $@: πρόκειται για καθολικές μεταβλητές πακέτου που η Perl runtime (και ό,τι καλείται από τον κώδικά σας) διαβάζει με γνωστά ονόματα. Μια επικάλυψη με my δεν θα τις επηρέαζε.
sub slurp {
my ($path) = @_;
open my $fh, "<", $path or die "open $path: $!";
local $/; # undef $/ for this sub only
return <$fh>; # read to EOF in one go
}
Η γραμμή local $/ πιο πάνω είναι το πιο κοινό ιδίωμα local στον πραγματικό κώδικα: αναιρεί προσωρινά τον διαχωριστή εγγραφών εισόδου ώστε η readline (<$fh>) να επιστρέψει ολόκληρο το αρχείο. Όταν η slurp επιστρέφει, η $/ επαναφέρεται σε ό,τι ήταν πριν - ακόμη και αν ο καλών την είχε επίσης αλλάξει.
Τι μπορείτε και τι δεν μπορείτε να τοπικοποιήσετε#
Μπορείτε να εφαρμόσετε local σε:
Βαθμωτά, πίνακες, hashes πακέτου -
local $Pkg::var,local @Pkg::arr,local %Pkg::hash. Το barewordlocal $varστοχεύει τη μεταβλητή στο τρέχον πακέτο.Ήδη δηλωμένες μεταβλητές
our- ηourδημιουργεί λεξιλογικό ψευδώνυμο προς μια μεταβλητή πακέτου, οπότε ηlocalπάνω της τοπικοποιεί την υποκείμενη καθολική.Μεμονωμένα στοιχεία και slices πινάκων/hashes πακέτου -
local $hash{key},local $array[3],local @hash{qw(a b)},local @array[0..2].Globs - η
local *nameδημιουργεί μια καινούργια εγγραφή στον πίνακα συμβόλων, έτσι ώστε οι$name,@name,%name,&nameκαι το filehandlenameνα επαναφέρονται δυναμικά όλα μαζί.Υπό συνθήκη lvalues -
local ($cond ? $v1 : $v2)όταν η επιλεγμένη διακλάδωση είναι η ίδια τοπικοποιήσιμη.
Δεν μπορείτε να εφαρμόσετε local σε:
Μια μεταβλητή
my. Οι μεταβλητέςmyείναι λεξιλογικές που ζουν σε pad, όχι στον πίνακα συμβόλων· δεν έχουν όνομα πακέτου ώστε ηlocalνα τις αποθηκεύσει κάτω από αυτό. Η προσπάθεια αποτελεί σφάλμα κατά τη μεταγλώττιση:Can't localize lexical variable $x.Μια μεταβλητή
state. Για τον ίδιο λόγο.Μόνο-για-ανάγνωση μαγικές καθολικές. Το
local $1 = 2αποτυγχάνει μεModification of a read-only value attempted- οι μεταβλητές σύλληψης δεν μπορούν να δεχθούν εκχώρηση. (Η μία εξαίρεση είναι η$_: ηlocal $_, από την 5.14, ρητά αφαιρεί τη μαγεία ώστε να μπορεί να επαναχρησιμοποιηθεί με ασφάλεια σε υπορουτίνα.)
Τοπικοποίηση στοιχείων σύνθετων τύπων#
Τα local $hash{key} και local $array[i] αποθηκεύουν τη συγκεκριμένη θέση, όχι την τιμή που τυχαίνει να βρίσκεται εκεί. Όταν η εμβέλεια τερματίζεται, η αρχική τιμή επαναφέρεται σε εκείνη ακριβώς τη θέση - ακόμη και αν το στοιχείο διαγράφηκε ή ο πίνακας κοντύνε στο μεταξύ. Ένα διαγραμμένο κλειδί hash επαναεμφανίζεται· ένα στοιχείο πίνακα που έγινε pop επανεμφανίζεται, γεμίζοντας τον πίνακα με undef αν χρειάζεται.
our %hash = (a => "is");
{
local $hash{a} = "drill";
delete $hash{a}; # gone for now...
}
print $hash{a}, "\n"; # ...but restored to "is"
Παραδείγματα#
Βασικά: δώστε σε μια καθολική μια προσωρινή τιμή για ένα μπλοκ. Οι υπορουτίνες που καλούνται μέσα από το μπλοκ βλέπουν τη νέα τιμή.
our $verbose = 0;
sub log_msg { print "[v=$verbose] $_[0]\n" }
{
local $verbose = 1;
log_msg("inside"); # prints "[v=1] inside"
}
log_msg("outside"); # prints "[v=0] outside"
Ιδίωμα slurp-αρχείου με $/:
my $content = do {
open my $fh, "<", $path or die "open $path: $!";
local $/; # list context for <> now reads all
<$fh>;
};
Παγιδεύστε προσωρινά την $@ ώστε μια εσωτερική eval να μην επικαλύψει το εκκρεμές σφάλμα του καλούντος:
sub try_cleanup {
local $@; # caller's $@ preserved
eval { risky_cleanup() };
# even if eval failed, caller's $@ is untouched
}
Προεπιλογές print σε στιλ Python, οριοθετημένες σε ένα μπλοκ:
{
local $, = " ";
local $\ = "\n";
print 1, 2, 3; # "1 2 3\n"
}
print 1, 2, 3; # "123" - defaults restored
Η μορφή λίστας χρειάζεται παρενθέσεις. Οι παρενθέσεις δίνουν επίσης στη δεξιά πλευρά περιβάλλον λίστας - ακριβώς όπως και η my:
our (@wid, %get);
local (@wid, %get) = (@defaults, %overrides);
Τοπικοποιήστε ένα μεμονωμένο στοιχείο hash - χρήσιμο για να περάσετε παρακάμψεις μέσα από μια κλήση χωρίς να αγγίξετε άσχετα κλειδιά:
our %config = (timeout => 30, retries => 3);
{
local $config{timeout} = 5;
do_probe(); # sees timeout => 5
}
# %config back to (timeout => 30, retries => 3)
Τοπικοποίηση glob - ολόκληρη η εγγραφή στον πίνακα συμβόλων για το LOG αντικαθίσταται:
{
local *LOG;
open LOG, ">", "/tmp/trace.$$" or die $!;
run_traced(); # sees our private LOG filehandle
}
# original LOG (if any) is back
Οριακές περιπτώσεις#
Τελεστής χρόνου εκτέλεσης, όχι δήλωση. Η
localεκτελείται κάθε φορά που ο έλεγχος φτάνει σε αυτήν. Μέσα σε βρόχο αποθηκεύει και επαναφέρει σε κάθε επανάληψη - μετρήσιμη επιβάρυνση. Βγάλτε την έξω από τον βρόχο όταν η πρόθεση είναι «για ολόκληρο τον βρόχο»:{ local $/ = "\n\n"; # once, not per iteration while (<$fh>) { ... } }
Η εκχώρηση αποτιμάται πριν από την αποθήκευση. Η δεξιά πλευρά εκτελείται στην περικλείουσα δυναμική εμβέλεια, οπότε η
local $x = $x + 1διαβάζει την παλιά$x, μετά αποθηκεύει, και κατόπιν εκχωρεί τη νέα τιμή.Το όριο εμβέλειας είναι δυναμικό, όχι λεξιλογικό. Η αποθήκευση αναιρείται όταν το τρέχον μπλοκ εξέρχεται σε χρόνο εκτέλεσης, όχι όταν το πηγαίο μπλοκ τερματίζεται κειμενικά. Η έξοδος μέσω
return,die,last,nextή μη-τοπικού goto εξακολουθεί να ενεργοποιεί την επαναφορά.Η
localσε μιαmyείναι σφάλμα κατά τη μεταγλώττιση. Ο αναλυτής απορρίπτει τοmy $x; local $x;μεCan't localize lexical variable $x. Χρησιμοποιήστεour(ή πλήρως προσδιορισμένο όνομα) αν πραγματικά χρειάζεστε δυναμική εμβέλεια σε εκείνο το όνομα.Πίνακες και hashes με tie δεν συμπεριφέρονται προς το παρόν όπως περιγράφει το POD - η τοπικοποίηση ολόκληρου του συσσωματώματος είναι ελαττωματική στο upstream. Η τοπικοποίηση μεμονωμένων στοιχείων ενός συσσωματώματος με tie είναι ασφαλής. Αυτή η επιφύλαξη κληρονομείται από την upstream Perl.
Στις μόνο-για-ανάγνωση μαγικές δεν μπορεί να γίνει εκχώρηση. Το
local $1 = "x"πεθαίνει σε χρόνο εκτέλεσης. Μπορείτε να κάνετεlocal $_(η μαγεία αφαιρείται από την 5.14) αλλά όχιlocal $1,local $&, κ.λπ.Αρνητικοί δείκτες πίνακα στο
local $array[-1]τεκμηριώνονται ως «ιδιαίτερα εκπληκτικοί» στο upstream· αντιμετωπίστε τη συμπεριφορά ως ασταθή και αποφύγετέ την.Το
delete localεπεκτείνει τηνlocalστην αφαίρεση στοιχείου: τοdelete local $hash{key}διαγράφει την εγγραφή για το τρέχον μπλοκ και την επαναφέρει κατά την έξοδο. Επιστρέφει την τιμή που υπήρχε πριν από την τοπικοποίηση.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
my- λεξιλογική (κατά τη μεταγλώττιση, με εμβέλεια μπλοκ) δήλωση· το σωστό εργαλείο όταν θέλετε μια πραγματικά ιδιωτική μεταβλητήour- λεξιλογικό ψευδώνυμο προς μια μεταβλητή πακέτου· συνηθισμένος εταίρος τηςlocalόταν η καθολική βρίσκεται σε άλλο πακέτοstate- επίμονη λεξιλογική· δεν μπορεί να τοπικοποιηθεί μεlocaldelete- σε συνδυασμό με τηνlocal(delete local $h{k}) για να περιορίσει τη διαγραφή στοιχείου στο τρέχον μπλοκeval- συνηθισμένος στόχος τηςlocal: ηlocal $@γύρω από εσωτερικήevalαποτρέπει τη διαρροή σφαλμάτων προς τον καλούντα$/- διαχωριστής εγγραφών εισόδου· καθιερωμένος στόχος τηςlocalγια αναγνώσεις αρχείων σε λειτουργία slurp$_- προεπιλεγμένο βαθμωτό· ηlocal $_αφαιρεί τη μαγεία (από την 5.14) ώστε μια υπορουτίνα να μπορεί να την επαναχρησιμοποιήσει με ασφάλεια$@- τελευταίο σφάλμαeval· ηlocal $@θωρακίζει τον καλούντα από το σφάλμα μιας εσωτερικήςeval