מערכים

shift#

הסרה והחזרה של האלמנט הראשון של מערך.

shift משנה את הארגומנט שלו: הוא מסיר את האלמנט באינדקס 0, מזיז כל אלמנט נותר למטה במיקום אחד, ומחזיר את הערך שהוסר. המערך מתכווץ באחד. אם המערך ריק, דבר אינו מוסר ומוחזר undef.

תקציר#

shift @arr
shift @$aref
shift                   # @_ inside a sub, @ARGV outside

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

הסקלר שהיה באינדקס 0, או undef אם המערך היה ריק. מכיוון ש־undef הוא גם אלמנט מערך חוקי, החזרת undef חשופה אינה משמעה בפני עצמה שהמערך היה ריק - השתמשו ב־scalar @arr או בבדיקת defined מוקדמת כשההבחנה משנה:

my @arr  = (undef, 'two');
my $item = shift @arr;      # undef - but @arr was not empty

מערך ברירת מחדל: @ARGV לעומת @_#

נקרא ללא ארגומנט, shift בוחר את המערך שלו מההקשר הסובב:

  • בתוך תת־שגרה שמית או אנונימית - @_. זו הדרך הניבית לצרוך ארגומנטים מיקומיים בזה אחר זה.

  • Outside any sub (including in the file scope of a script, and in eval STRING, BEGIN, INIT, CHECK, UNITCHECK, END blocks)

    • @ARGV. This is how top-of-script argument consumption is usually written.

הבחירה נעשית בזמן הידור על בסיס מיקום לקסיקלי, לא בזמן ריצה. shift בתוך sub תמיד מכוון ל־@_ גם אם ה־sub נקרא מתחום הקובץ.

דוגמאות#

צריכת ארגומנט מיקומי בודד בתוך מתודה. זוהי השורה הראשונה הקנונית של כמעט כל מתודה מונחית־עצמים ב־Perl:

sub greet {
    my $self = shift;
    my $name = shift;
    return "hello, $name, from $self";
}

אותה מתודה כתובה עם פרוסת @_ של list-unpack. שתי הצורות הן ניביות; shift מנצח כשרוצים לקלף את ה־invocant לפני שמחליטים מה לעשות עם שאר @_:

sub greet {
    my ($self, $name) = @_;
    return "hello, $name, from $self";
}

צריכת @ARGV בראש סקריפט, ארגומנט אחד בכל פעם:

my $mode = shift // 'default';       # first CLI arg, or 'default'
my $path = shift // die "need a path\n";
# @ARGV now holds whatever is left

תור FIFO: push על הזנב, shift מהראש:

my @queue;
push @queue, 'a', 'b', 'c';
while (defined(my $job = shift @queue)) {
    handle($job);
}

Dereference של הפניה למערך במקום - shift עובד על @$aref בדיוק כמו על מערך שמי:

my $aref = [10, 20, 30];
my $head = shift @$aref;             # 10, $aref now [20, 30]

מקרי קצה#

  • מערך ריק: מחזיר undef ומשאיר את המערך ללא שינוי. shift על מערך ריק אינו שגיאה.

  • מורכבות היא O(n): כל אלמנט נותר מוזז למטה בחריץ אחד. עבור מערכים גדולים המשמשים כתורים זה מצטבר. כאשר סדר FIFO אינו דרוש, pop הוא O(1); כאשר הוא דרוש, שקלו מבנה נתונים בסגנון deque או צמד מחסניות במקום לבצע shift על מערך בן מיליון אלמנטים בלולאה.

  • shift ללא ארגומנט רגיש להקשר לפי מיקום לקסיקלי: בתוך sub הוא מכוון ל־@_, מחוצה לו הוא מכוון ל־@ARGV. הזזת שורת קוד בין התחומים האלה משנה בשקט איזה מערך הוא משנה.

  • מערכים קשורים: shift קורא למתודה SHIFT על העצם הקשור אם אחת מוגדרת; אחרת הוא חוזר ל־FETCH על אלמנט 0, ואז DELETE, ואז רצף של צמדי FETCH/STORE כדי להזיז את האלמנטים הנותרים למטה, ואז STORESIZE. מטפל SHIFT מותאם אישית כמעט תמיד שווה לכתוב לצורך ביצועים.

  • הפניות למערך: shift @$aref ו־shift @{ $expr } שניהם עובדים. shift $aref (ללא ה־sigil @) הייתה תכונה ניסיונית שהוספה ב־Perl 5.14 והוסרה ב־5.24 - זוהי שגיאת תחביר בגרסת Perl ש־pperl מכוון אליה.

  • shift הוא צרכן־lvalue, לא lvalue: לא ניתן להציב לתוצאה של shift כדי לשנות את המערך. השתמשו ב־splice או בהשמה ישירה לאינדקס לשם כך.

  • ערך החזרה בהקשר רשימה: shift תמיד מחזיר סקלר בודד. השמת תוצאתו לרשימה - my ($x) = shift @arr - עובדת רק מכיוון שהסקלר הבודד ממלא את חריץ הרשימה הראשון; שאר החריצים הם undef. השתמשו ב־splice כדי להסיר מספר אלמנטים בבת אחת.

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

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

ראו גם#

  • pop - הסרה והחזרה של האלמנט האחרון; O(1), הבחירה הנכונה כשסדר FIFO אינו דרוש

  • push - צירוף לזנב; משולב עם shift להוות תור FIFO

  • unshift - הוספה לראש; ההפוך של shift, וגם O(n) מאותה סיבה

  • splice - הסרה, הוספה או החלפה של כל ריצה רציפה של אלמנטים; הכלי הכללי כאשר shift / pop / unshift / push אינם מספיקים

  • @ARGV - מערך ברירת המחדל ש־shift צורך בתחום הקובץ

  • @_ - מערך ברירת המחדל ש־shift צורך בתוך sub; מחזיק את רשימת הארגומנטים של הקורא