רשימות

all#

בדיקה אם BLOCK מחזיר אמת עבור כל איבר של LIST.

all סורק את LIST משמאל לימין, יוצר alias של $_ לכל איבר בתורו ומעריך את BLOCK עם אותו איבר. הוא מחזיר ערך אמת אם כל הערכה מניבה אמת, וערך שקר ברגע שהערכה כלשהי מניבה שקר. ברגע שאיבר אחד גורם לבלוק להיות שקרי, all עוצר ומחזיר — הוא אינו מעריך את הבלוק עבור האיברים הנותרים.

זוהי מילת המפתח all ברמת השפה, מופעלת על ידי תכונת keyword_all. היא מובחנת מ־List::Util::all — ראו מקרי קצה להלן.

תקציר#

use feature 'keyword_all';
no warnings 'experimental::keyword_all';

all { /\w+/ } @words;
all { defined $_ } @list;        # canonical "all defined" check
all { $_ > 0 } @numbers;

מה מוחזר#

ערך בוליאני. אמת אם כל איבר עובר, שקר אחרת. ערכי האמת/שקר המדויקים אינם מוגדרים — יש להתייחס לתוצאה כאל תנאי, לא כאל נתון להעברה.

רשימה ריקה מחזירה אמת. זוהי אמת ריקה: הטענה ”כל איבר מקיים את BLOCK“ אמיתית טריוויאלית כשאין איברים לבדוק. זהו מקור ההפתעה הנפוץ ביותר עם all:

all { $_ > 0 } ();               # TRUE — no elements, nothing to fail

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

if (@numbers && all { $_ > 0 } @numbers) { ... }

מצב גלובלי שהפונקציה נוגעת בו#

  • $_ — מקבל alias לכל איבר של LIST בתורו למשך זמן הבלוק. מכיוון שזהו alias ולא העתק, השמה ל־$_ בתוך הבלוק משנה את איבר הרשימה הבסיסי. הערך הקודם של $_ משוחזר כאשר all חוזר.

דוגמאות#

בדיקה שכל ערך ברשימה מוגדר — השימוש הקנוני:

my @row = get_record();
die "missing field" unless all { defined $_ } @row;

בדיקה שכל מספר חיובי:

my @prices = (1.99, 4.50, 0.99);
say "ok" if all { $_ > 0 } @prices;         # ok

תיקוף רשומה שבה כל שדה חייב להתאים לפרדיקט שלו. יש לשלב מספר בדיקות בתוך הבלוק במקום לשרשר קריאות all:

my @fields = ($name, $age, $email);
my $ok = all {
    defined $_ && length $_ > 0
} @fields;

שילוב all עם any לבדיקה בלעדית — לפחות התאמה אחת, אך לא כל האיברים זהים:

if (any { $_ eq 'admin' } @roles
    && !all { $_ eq 'admin' } @roles) {
    say "mixed roles, including admin";
}

התנהגות קצר־לוגי: הבלוק רץ רק עד לכישלון הראשון. שימושי עבור פרדיקטים עם תופעות לוואי או עלות:

all { expensive_check($_) } @candidates;    # stops at first failure

מקרי קצה#

  • רשימה ריקה מחזירה אמת. אמת ריקה. יש להגן עם @list && all { ... } @list כאשר ריקנות אמורה להיכשל.

  • קצר־לוגי על שקר ראשון. הבלוק אינו נקרא עבור איבר כלשהו לאחר הכישלון הראשון. אין להסתמך על כך שתופעות לוואי בבלוק ירוצו עבור כל איבר — יש להשתמש בלולאת for אם נדרש כך.

  • $_ הוא alias, לא העתק. שינוי $_ בתוך הבלוק משנה את איבר הרשימה:

    my @xs = (1, 2, 3);
    all { $_++; $_ > 0 } @xs;
    # @xs is now (2, 3, 4)
    
  • ניסיוני תחת 5.42. התכונה פולטת אזהרת זמן־קומפילציה בקטגוריה experimental::keyword_all אלא אם אותה קטגוריה מושתקת:

    no warnings 'experimental::keyword_all';
    
  • אינו זהה ל־List::Util::all. המובנה הוא מילת מפתח של השפה המופעלת על ידי תכונת keyword_all ומפענח את BLOCK כבלוק אמיתי (ללא sub מוביל, ללא פסיק נגרר). List::Util::all היא תת־שגרה רגילה המיובאת ממודול ומקבלת ארגומנט code reference / block prototype. למרבית המטרות המעשיות הן מתנהגות זהה ברשימות שאינן ריקות, אך:

    • צורת מילת המפתח היא מבנה ברמת ה־parser וניתנת לאופטימיזציה אגרסיבית יותר.

    • השניים אינם חולקים מימוש ולא קטגוריית אזהרה.

    • קוד הצריך לרוץ על Perl מלפני 5.42 צריך להשתמש ב־List::Util::all.

  • צורת grep שווה־ערך. all { COND } @xs שווה־ערך סמנטית ל־@xs == grep { COND } @xs — אך grep תמיד מעריך את הבלוק עבור כל איבר, ולכן חסרה לו התנהגות הקצר־לוגי של all.

הבדלים מן ה-upstream#

תואם מלא ל־Perl 5.42 upstream.

ראו גם#

  • any — אמת אם הבלוק מחזיר אמת עבור לפחות איבר אחד; האופרטור הראי ל־all

  • grep — מעריך את הבלוק עבור כל איבר ומחזיר התאמות; scalar @list == grep { } @list הוא all ללא הקצר־לוגי

  • defined — הפרדיקט בתוך הבדיקה הקנונית all { defined $_ } @list

  • List::Util::all — שווה־ערך ברמת המודול הזמין על Perl ישן מ־5.42; מספק גם none ו־notall שאין להם מקבילה ברמת השפה

  • List::Util::any — מקבילה ברמת המודול למילת המפתח any, לצד none ו־notall לקטביות ההפוכות