local#
שומר את הערך הנוכחי של משתנה חבילה ומשחזר אותו ביציאה מהתחום הסובב.
local הוא אופרטור התחום הדינמי. הוא אינו מצהיר על משתנה חדש - הוא נשלח לתוך משתנה חבילה (גלובלי) קיים, גונז את הערך הנוכחי במחסנית שמירה מוסתרת, ודואג שהערך המקורי יוחזר כשהבקרה עוזבת את הבלוק הנוכחי, eval, או do FILE. תת־שגרות הנקראות רואות את הערך הזמני. עבור רוב הצרכים של ״אני רוצה משתנה מקומי לבלוק הזה״, הכלי הנכון הוא my; פנו ל־local ספציפית כשהמשתנה חייב להיות גלובלי לחבילה - משתני הפיסוק, מטפלי קובץ, או רשומות בטבלת הסמלים - ואתם רוצים שלאותו גלובלי יהיה ערך שונה במשך בלוק וכל תת־שגרה שהוא קורא לה.
תקציר#
local EXPR
local $var
local $var = EXPR
local (@list) = LIST
local $hash{key}
local $array[i]
local *GLOB
מה מקבלים בחזרה#
הערך של הביטוי שעבר localize (הערך החדש, לאחר כל השמה באותה הצהרה). ניהול מחסנית השמירה הוא תופעת לוואי; ערך ההחזרה חשוב רק כאשר local מופיע בתוך ביטוי גדול יותר:
our $x = 2;
foo($x, local $x = $x + 1, $x); # foo() receives (2, 3, 3)
תחום דינמי, לא תחום לקסיקלי#
local ו־my הם זנים שונים של תיחום:
myיוצר משתנה חדש בעל תיחום לקסיקלי. רק קוד שטקסטואלית בתוך הבלוק הסובב יכול לראותו. תת־שגרות הנקראות אינן יכולות.localאינו יוצר דבר. הוא דורס באופן זמני את הערך של משתנה חבילה קיים. כל פיסת קוד - הבלוק הזה וכל תת־שגרה שהוא קורא לה, ישירות או טרנזיטיבית - רואה את הערך החדש עד שהתחום מסתיים.
זו הסיבה ש־local הוא הכלי הנכון עבור משתני פיסוק כמו $/, $\, $,, $_, ו־$@: אלה גלובלים של חבילה ש־runtime של Perl (וכל דבר שנקרא מהקוד שלכם) קורא בשמות ידועים. הצללה של 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 חוזרת, $/ משוחזר לכל מה שהיה לפני - גם אם הקורא שינה אותו גם.
מה ניתן ומה לא ניתן ל־localize#
ניתן לעשות localize ל־:
סקלרים, מערכים, והאשים של חבילה -
local $Pkg::var,local @Pkg::arr,local %Pkg::hash.local $varכ־bareword מכוון אל המשתנה בחבילה הנוכחית.משתני
ourשכבר הוצהרו -ourיוצר כינוי לקסיקלי למשתנה חבילה, אזlocalעליו עושה localize לגלובלי הבסיסי.אלמנטים בודדים ופלחים של מערכים/האשים של חבילה -
local $hash{key},local $array[3],local @hash{qw(a b)},local @array[0..2].Globs -
local *nameיוצר רשומת טבלת־סמלים חדשה כך ש־$name,@name,%name,&name, ומטפל הקובץnameכולם מאופסים דינמית יחד.lvalues מותנים -
local ($cond ? $v1 : $v2)כאשר הענף הנבחר עצמו ניתן ל־localize.
אינכם יכולים לעשות localize ל־:
משתנה
my. משתניmyהם לקסיקליים החיים ב־pad, לא בטבלת הסמלים; אין להם שם חבילה ש־localיוכל לשמור תחתיו. ניסיון לעשות זאת הוא שגיאת זמן־הידור:Can't localize lexical variable $x.משתנה
state. אותה סיבה.גלובלים קסומים לקריאה־בלבד.
local $1 = 2נכשל עםModification of a read-only value attempted- משתני הלכידה אינם ניתנים להשמה. (היוצא־דופן הוא$_:local $_, מאז 5.14, מסיר במפורש קסם כך שניתן להשתמש בו מחדש בבטחה בתת־שגרה.)
Localize של אלמנטים מטיפוס מורכב#
local $hash{key} ו־local $array[i] שומרים את החריץ הנקוב, לא את הערך שבמקרה נמצא שם. כאשר התחום מסתיים, הערך המקורי משוחזר לאותו חריץ - גם אם האלמנט נמחק או שהמערך התקצר בינתיים. מפתח האש שנמחק קופץ חזרה; אלמנט מערך שעבר 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-a-file עם $/:
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);
Localize של אלמנט האש בודד - שימושי להשחלת דריסות דרך קריאה מבלי לגעת במפתחות לא־קשורים:
our %config = (timeout => 30, retries => 3);
{
local $config{timeout} = 5;
do_probe(); # sees timeout => 5
}
# %config back to (timeout => 30, retries => 3)
Localize של 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(או שם מלא) אם אתם זקוקים באמת לתיחום דינמי על אותו שם.מערכים והאשים שעברו tie אינם מתנהגים כעת באופן שה־POD מתאר - localize של האגרגט כולו מלא־באגים במקור. localize של אלמנטים בודדים של אגרגט שעבר tie הוא בטוח. הסתייגות זו עוברת בירושה מ־Perl המקורי.
גלובלים קסומים לקריאה־בלבד אינם ניתנים להשמה.
local $1 = "x"מת בזמן ריצה. אתם יכוליםlocal $_(קסם מוסר מאז 5.14) אבל לאlocal $1,local $&, וכו׳.אינדקסים שליליים של מערך ב־
local $array[-1]מתועדים כ״במיוחד מפתיעים״ במקור; התייחסו להתנהגות כבלתי־יציבה והימנעו.delete localמרחיב אתlocalלהסרת אלמנט:delete local $hash{key}מוחק את הרשומה עבור הבלוק הנוכחי ומשחזר אותה ביציאה. הוא מחזיר את הערך שהיה שם לפני ה־localization.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
my- הצהרה לקסיקלית (זמן־הידור, בתחום בלוק); הכלי הנכון כשרוצים משתנה פרטי באמתour- כינוי לקסיקלי למשתנה חבילה; שותף נפוץ ל־localכאשר הגלובלי בחבילה אחרתstate- לקסיקלי קבוע; אינו ניתן ל־localizedelete- בשילוב עםlocal(delete local $h{k}) לתחימת מחיקת אלמנט לבלוק הנוכחיeval- יעדlocalנפוץ:local $@סביבevalפנימי מונע ממנו לדלוף שגיאות לקורא$/- מפריד רשומת קלט; יעדlocalקנוני לקריאות קובץ במצב slurp$_- סקלר ברירת מחדל;local $_מסיר קסם (מאז 5.14) כך שתת־שגרה יכולה להשתמש בו מחדש בבטחה$@- שגיאת ה־evalהאחרונה;local $@מגן על הקורא מפני שגיאתevalפנימי