הצהרה#

כל תת־שגרה היא אחד משלושה דברים: תת־שגרה בעלת שם הכבולה לחבילה, תת־שגרה אנונימית המאוחסנת בהפניה לקוד, או תת־שגרה לקסיקלית הכבולה למשבצת דמוית־my בתחום הנוכחי. צורת ההצהרה בוחרת אחת מהן; כל השאר (prototype, חתימה, מאפיינים, גוף) מעטר אותה.

תת־שגרות בעלות שם#

sub greet {
    my ($name) = @_;
    return "Hello, $name!";
}

greet("Alice");                  # "Hello, Alice!"

השם greet נכבל בטבלת הסמלים של החבילה הנוכחית תחת משבצת ה־& - אותה משבצת שזמן־הריצה מחפש בה כשאתה קורא greet(...) או \&greet. תת־שגרות בעלות שם גלויות לכל קוד שרץ לאחר שפקודת ה־sub מהודרת; בפועל ”מהודרת“ משמעה ”הקובץ נותח עד ההצהרה“, שזה כמעט תמיד מה שאתה רוצה.

ניתן גם להצהיר על תת־שגרה בעלת שם בשני חלקים - הצהרה מקדימה והגדרה:

sub later;                       # promise: a sub named 'later' will exist
sub later {                      # fulfilment
    return 42;
}

ההצהרה המקדימה שימושית בעיקר כש־prototypes צריכים להיכנס לתוקף עבור קריאות רקורסיביות (ה־prototype חייב להיות גלוי לפני שהקריאה הרקורסיבית מנותחת) או כשברצונך להשתיק אזהרות ”Bareword not allowed“ עבור קוד הקורא לתת־השגרה לפני הגדרתה.

קריאה לתת־שגרה לפי שם#

greet("Alice");                  # most common form
greet "Alice";                   # parens optional once predeclared
&greet("Alice");                 # legacy: disables prototype checking
&greet;                          # legacy: pass current @_ as the call's @_

צורת ה־&־החשוף (&greet ללא סוגריים) היא שריד מ־perl4 עם שימוש לגיטימי אחד שנותר: העברת ה־@_ הנוכחי ישירות ללא העתקה. ראה רקורסיה עבור goto &greet, הגרסה של קריאת הזנב.

תת־שגרות אנונימיות#

my $double = sub {
    my ($x) = @_;
    return $x * 2;
};

$double->(7);                    # 14

הביטוי sub { ... } מוערך כהפניה לקוד. הוא לוכד כל משתנה לקסיקלי (my/state) מהתחום העוטף שלו - ראה תיחום - ומופעל באמצעות ->() או בעזרת הצורות הישנות &$double() / &{$double}().

תת־שגרות אנונימיות הן הדרך שבה כל callback ב־Perl עובד:

my @sorted = sort { $a <=> $b } @list;
my @big    = grep { $_ > 100   } @list;
my @str    = map  { "<$_>"     } @list;

הן גם אבן הבניין עבור closures, טבלאות שיגור, ועצמי דמה. טבלת שיגור:

my %op = (
    add => sub { $_[0] + $_[1] },
    sub => sub { $_[0] - $_[1] },
    mul => sub { $_[0] * $_[1] },
);

my $result = $op{$cmd}->($x, $y);

הפניות לקוד#

הפניה לקוד היא סקלר מהמעלה הראשונה המחזיק תת־שגרה. אתה מקבל אחת מ־sub { ... }, מ־\&named_sub, או מחיפוש מתודה עם can:

my $cref = \&greet;              # ref to named sub
my $cref = sub { ... };          # anonymous
my $cref = $obj->can('method');  # method lookup, returns code ref or undef

$cref->("Alice");                # invocation
&$cref("Alice");                 # legacy invocation

בתוך הפניה לקוד, תת־השגרה שומרת על זהותה: \&greet היא תמיד אותה הפניה למשך כל חיי ה־&greet של החבילה. תת־שגרות אנונימיות הן הפניות נבדלות בכל פעם שהביטוי sub { ... } מוערך - זה מה שגורם למפעלי closure לעבוד.

תת־שגרות לקסיקליות#

תת־שגרה לקסיקלית מוצהרת עם my sub (וה־state sub וה־our sub המקבילים):

sub outer {
    my sub helper {
        my ($x) = @_;
        return $x * 2;
    }

    return helper(21);           # 42
}

helper(1);                       # error: undefined subroutine
                                 # (helper isn't visible here)

my sub שימושית ביותר בתוך פונקציות ארוכות שבהן ברצונך עוזר פרטי מבלי לזהם את מרחב השמות של החבילה. היא אינה בשימוש נרחב בשטח, אך היא הכלי הנכון כשברצונך כימוס אמיתי. ראה תיחום עבור הגרסאות state ו־our.

הצהרה מוקדמת#

הצהרה מוקדמת היא פקודת sub NAME; (ללא גוף, ללא סוגריים מסולסלים). שלוש סיבות לכתוב אחת:

# 1. Allow the sub to be called without parens before it's defined
sub later;
later;                           # parses as later()

# 2. Make a prototype visible before the body is reached
sub mypush (\@@);
sub mypush (\@@) { ... }

# 3. Document an exported API at the top of the file
sub greet;
sub farewell;
sub welcome;
# ... actual definitions further down

בקוד מודרני סיבות (1) ו־(3) הן בעיקר סגנוניות. סיבה (2) היא דרישה אמיתית כשאתה משתמש ב־prototypes; ראה prototypes.

מה אינך יכול לעשות#

  • אינך יכול להגדיר מחדש פונקציה מובנית באמצעות sub print { ... } ולגרום ל־Perl להשתמש בשלך בשקט. דריסת פונקציות מובנות עוברת דרך CORE::GLOBAL::print ומתועדת תחת מאפיינים ועמוד הפירוט של prototype.

  • אינך יכול שתהיינה שתי תת־שגרות בעלות אותו שם באותה חבילה ללא אזהרת ”Subroutine NAME redefined“. או ששנה את השם או שתתכוון להגדרה מחדש באמת (והשתק את האזהרה עם no warnings 'redefine';).

  • אינך יכול לתת הצהרה מקדימה וגוף עם prototypes שונים. שתי ההצהרות חייבות להסכים זו עם זו.

ראו גם#

  • ארגומנטים ו־@_ - מה שהגוף רואה ברגע שהקריאה מתבצעת.

  • תיחום - מה my, our, local, ו־state עושים למשתנים בתוך הגוף.

  • sub - עמוד ה־perlfunc של מילת המפתח.

  • prototype - הסתכלות־פנימית בזמן־ריצה על ה־prototype של תת־שגרה, והגשר לדריסת פונקציות מובנות.

  • אופרטור החץ - הפעלת ->() של הפניות לקוד.