זרימת בקרה · תיחום

caller#

מחזיר מידע על תת־השגרה, eval, או require שקראו לקוד המבוצע כעת.

caller סורק את מחסנית הקריאות. ללא ארגומנט הוא מחזיר רשומה קצרה בת שלושה אלמנטים המזהה מי קרא לנו. עם ארגומנט מספרי EXPR הוא סורק EXPR מסגרות נוספות אחורה ומחזיר רשומה ארוכה יותר בת אחד־עשר אלמנטים - הצורה שבה משתמשים המנפה, מודולי stack-trace, ומנגנון warn/die כדי לקשט אבחונים בהקשר קובץ־ושורה. מסגרות XS אינן נראות ל־caller; מסגרת ה־pure-Perl הבאה צפה במקומן.

תקציר#

caller
caller EXPR

מה מקבלים בחזרה#

בהקשר סקלרי, שם החבילה של הקורא, או undef אם אין קורא (כלומר, אנו ברמה העליונה של הקובץ, לא בתוך sub, eval, או require):

my $pkg = caller;

בהקשר רשימה ללא ארגומנט, שלושה אלמנטים - החבילה, הקובץ ומספר השורה של הקורא הישיר:

# 0         1          2
my ($package, $filename, $line) = caller;

בהקשר רשימה עם ארגומנט מספרי, אחד־עשר אלמנטים המתארים את המסגרת EXPR רמות מעלה. 0 הוא הקורא הישיר, 1 הוא הקורא שלו, וכן הלאה:

# 0         1          2      3            4
my ($package, $filename, $line, $subroutine, $hasargs,

#   5          6          7            8       9         10
    $wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash)
  = caller($i);

אחד־עשר השדות, לפי הסדר:

  • $package, $filename, $line - מיקום אתר הקריאה בתוך הקורא של אותה מסגרת. אותם שלושה ערכים שהצורה הקצרה מחזירה.

  • $subroutine - שם מלא של תת־השגרה שאליה שייכת המסגרת, למשל "Foo::bar". עבור מסגרת eval זוהי המחרוזת המילולית "(eval)". אם תת־השגרה הוסרה מטבלת הסמלים מאז הקריאה, הערך הוא "(unknown)".

  • $hasargs - אמת אם הוקצה @_ חדש עבור המסגרת. שקר עבור מסגרות eval ו־require.

  • $wantarray - ההקשר שבו נקראה המסגרת, כפי ש־wantarray היה מדווח עליו: אמת עבור רשימה, מוגדר־אך־שקר ("") עבור סקלר, undef עבור void.

  • $evaltext - עבור מסגרת eval EXPR, טקסט המקור שהודר. לא־מוגדר עבור eval BLOCK ועבור מסגרות שאינן eval.

  • $is_require - אמת אם המסגרת נוצרה על־ידי require או use (כל use יוצר מסגרת require המקוננת בתוך מסגרת eval EXPR).

  • $hints - הערך של $^H בנקודה שבה הודר קוד המסגרת. פנימי; המבנה אינו יציב בין גרסאות Perl.

  • $bitmask - הערך של ${^WARNING_BITS} באותה נקודה. גם זה פנימי.

  • $hinthash - הפניה ל־האש %^H שנלכדה בזמן ההידור, או undef אם היא הייתה ריקה. אל תשנו אותה - ההפניה מצביעה ל־optree החי.

מצב גלובלי שהוא נוגע בו#

  • @DB::args - נקבע כתופעת לוואי כאשר caller נקרא עם ארגומנט מתוך החבילה DB. רשימת הארגומנטים של הקורא מקושרת כ־alias למערך זה לצורך שימוש המנפה. ראו מקרי קצה למטה - זוהי השתדלות מיטבית עם פינות חדות.

  • $^H, ${^WARNING_BITS}, %^H - נקראים מהמצב המהודר של מסגרת היעד כדי לאכלס את $hints, $bitmask, $hinthash.

דוגמאות#

למצוא את החבילה של הקורא הישיר ולדווח ליומן הנכון:

sub log_for_caller {
    my $pkg = caller;
    warn "[$pkg] @_\n";
}

להפיק תג מיקום בסגנון warn. caller מחזיר את שם הקובץ והשורה של אתר הקריאה מסגרת אחת למעלה, וזה כמעט תמיד המידע שבאמת רוצים באבחון:

sub note {
    my (undef, $file, $line) = caller;
    print STDERR "note at $file line $line: @_\n";
}

לסרוק את המחסנית המלאה. לבצע איטרציה על caller($i) עד שהוא מחזיר רשימה ריקה:

sub stacktrace {
    my @frames;
    for (my $i = 0; my @f = caller($i); $i++) {
        push @frames, \@f;
    }
    return @frames;
}

לזהות האם תת־השגרה הנוכחית נקראה בהקשר רשימה, סקלרי, או void. זהו wantarray ברמה הנוכחית, אבל עבור מסגרת של מישהו אחר ניגשים אליה דרך caller:

sub describe_parent_context {
    my $wa = (caller(1))[5];
    return !defined $wa ? "void"
         :  $wa         ? "list"
         :                "scalar";
}

להבחין בין מסגרת require/use לבין eval רגיל:

sub called_from_require {
    my @f = caller(1);
    return @f && $f[7];             # field 7 is $is_require
}

להציג מסגרת בודדת בדרך שבה הפורמטר ברירת המחדל של die / Carp עושה זאת - "at FILE line LINE":

sub location_tag {
    my $depth = shift // 0;
    my (undef, $file, $line) = caller($depth);
    return defined $file ? "at $file line $line" : "at top level";
}

מקרי קצה#

  • הקשר סקלרי, אין קורא: ברמה העליונה של סקריפט, scalar caller מחזיר undef, ו־caller בהקשר רשימה מחזיר רשימה ריקה. ניב נפוץ עבור ״האם אני נטען כמודול על־ידי require, או רץ כסקריפט?״ הוא caller() ? ... : ....

  • מסגרות XS מדולגות. caller מדווח רק על מסגרות pure-Perl. אם תת־שגרת pure-Perl הופעלה על־ידי תת־שגרת XS שהופעלה על־ידי תת־שגרת pure-Perl אחרת, caller(0) מתת־השגרה הפנימית מדווח על תת־השגרת pure-Perl החיצונית - שכבת ה־XS אינה נראית. עומקי מחסנית הנמדדים עם caller אינם כוללים אפוא את מעטפות ה־XS.

  • למסגרות eval אין ארגומנטים. $hasargs הוא שקר עבור מסגרות eval ו־require, ו־$subroutine הוא המחרוזת המילולית "(eval)" - לא החבילה של הקוד הסובב.

  • eval BLOCK מול eval EXPR. שניהם נותנים $subroutine eq "(eval)". רק eval EXPR ממלא את $evaltext; eval BLOCK משאיר אותו undef.

  • use יוצר שתי מסגרות. הצהרת use Foo מהודרת כ־BEGIN { require Foo; Foo->import; }, ו־require עצמו מיושם כ־eval EXPR. סריקת המחסנית דרך שורת use רואה אפוא מסגרת eval מסומנת ב־require בתוך מסגרת eval רגילה. בדקו את $is_require כדי להבחין.

  • תת־שגרות (unknown). אם תת־השגרה הנקובה במסגרת נמחקה מטבלת הסמלים (ניתוח טבלת־סמלים, delete $Foo::{bar}) בין הקריאה לבין ה־caller, $subroutine נקרא "(unknown)".

  • לולאות ובלוקי try אינם מסגרות. while, for, foreach, ו־try אינם יוצרים מסגרות קריאה. caller רואה רק קריאות לתת־שגרות ו־evalים.

  • מסגרות שהושמטו על־ידי המייעל. המייעל עשוי להסיר tail-call ומסגרות דומות לפני ש־caller יכול לצפות בהן. עבור caller(N) עם N > 1, המסגרת שמתקבלת אינה מובטחת להיות המסגרת שציפיתם לה. אין לקודד את עומק המחסנית כחוזה נושא־עומס.

  • @DB::args הוא השתדלות מיטבית. הוא מאוכלס רק כאשר caller נקרא עם ארגומנט מתוך החבילה DB. הערכים הם aliases לתוך @_ של מסגרת היעד, לא עותקים - ולכן:

    • שינויים שהמסגרת כבר ביצעה ב־@_ נראים; הערכים המקוריים מזמן הקריאה אינם נשמרים.

    • shift @_ בתוך המסגרת מבוטל בדרך כלל ב־@DB::args, אבל pop @_, splices, או לקיחת הפניה ל־@_ כולם שוברים זאת.

    • אלמנטים עשויים להיות משוחררים ומשומשים מחדש עבור ערכים אחרים עד הזמן שתקראו אותם.

    • מצב מיושן מקריאת caller קודמת עשוי עדיין להיות ב־@DB::args אם הקריאה הנוכחית לא הפעילה רענון. השתמשו בו ל־backtraces ולתצוגת מנפה; אל תסתמכו עליו ללוגיקת התוכנית.

  • $hinthash חי. הפניית ההאש בשדה 10 מצביעה לתמונת ה־%^H בפועל המוטמעת ב־optree. שינוי תוכנו משנה את מצב המהדר. קראו אותו; אל תכתבו אליו.

  • שם קובץ ושורה ניתנים לשכתוב. הוראות #line וכל דבר אחר שמנגנון ה־“Plain Old Comments (Not!)“ מזהה (ראו perlsyn) משנים את הערכים ש־caller מדווח, בדיוק כפי שהם משנים את __FILE__ ו־__LINE__.

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • die - מעלה חריגה; הודעת ברירת המחדל שלו משתמשת באותו מידע קובץ־ושורה ש־caller חושף

  • eval - יוצר מסגרות ש־caller מסמן עם $subroutine eq "(eval)" ועשוי למלא $evaltext / $is_require

  • wantarray - מדווח על הקשר הקריאה של המסגרת הנוכחית; אותו ערך מופיע כשדה 5 של caller(N) עבור המסגרת N רמות מעלה

  • $^H - ביטי רמז של זמן ההידור; מוצגים כשדה 8

  • %^H - האש רמזים של זמן ההידור; מוצגת כשדה 10

  • ${^WARNING_BITS} - מסכת ביטים של אזהרות; מוצגת כשדה 9