בחלק זה של המדריך לפרל נסתכל על רגישות להקשר (context) in Perl.

בעברית, כמו בשפות מדוברות אחרות, למילים יכולה להיות יותר ממשמעות אחת. למשל למילה "סיפר" יש יותר ממשמעות אחת

הוא סיפר אותי.

הוא סיפר לי משהו.

אנחנו מבינים מה המשמעות הנכונה לפי המשפטים שמסביב למילה. זה נקרא הקשר.

גם בפרל 5 זה עובד כך. למלים, לקריאות לפונקציות ולביטויים אחרים יכולות להיות משמעויות שונות בתלות בהקשר. זה קצת מקשה על לימוד השפה, אך זה נותן לה יכולת הבעה רחבה יותר.

בפרל יש שני הקשרים עיקריים: הקשר סקלרי (SCALAR) והקשר רשימתי (LIST .

מערכים בהקשר רשימתי

נראה דוגמה:

my @words = ('Foo', 'Bar', 'Baz');
my @names = @words;

אחרי ההצבה המערך @names מכיל עותק של האלמנטים שהיו במערך @words;

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

מערך בהקשר סקלרי

my @words = ('Foo', 'Bar', 'Baz');
my $people =  @words;

הפעם הצבנו את המערך @words במשתנה הסקלרי$people שפות שונות מטפלות במקרה הזה בצורה שונה, בפרל הצבה כזאת מציבה את מספר האלמנטיםם במערך במשתנה הסקלרי.

התנהגות זו היא בחירה די שרירותית, ובדוגמה שראינו לא ממש שימושית, אך יש מקרים שבהם התנהגות זו היא מאוד שימושית.

הקשר סקלרי והקשר רשימתי

ההקשרים שראינו נקראים הקשר סקלרי והקשר רשימתי. כלומר האם אנחנו מצפים לקבל ערך יחיד (בהקשר סקלרי) או מספר ערכים (בהקשר רשימתי). בהקשר רשימתי הערכים עשויים להיות 0, 1, 2, או כל מספר אחר.

ההקשר של משפט התנאי if

הסתכלו בדוגמה הבאה:

my @words = ('Foo', 'Bar', 'Baz');

if (@words) {
   say "There are some words in the array";
}

בחלק התנאי של משפט ה- ifאנחנו מצפים לערך אחד בלבד. מכאן שההקשר חייב להיות הקשר סקלרי.

אנחנו כבר יודעים שערכו של מערך בהקשר סקלרי הוא מספר האלמנטים במער. כמו כן אנחנו יודעים שהמספר הזה הוא 0 (כלומרFALSE) כשהמערך ריק, ומספר חיובי כלשהו (כלומר TRUE), כשהמערך מכיל ערך אחד או יותר.

אז בגלל אותה החלטה שרירותית שראינו קודם, הקוד if (@words) בודק אם יש למערך תוכן כלשהו ונכשל אם המערך ריק.

אם נהפוך את התנאי if (! @words) יהיה true אם המערך ריק.

הקשר סקלרי והקשר רשימתי

בחלק הקודם ראינו איך localtime() מתנהג בהקשר סקלרי ובהקשר רשימתי, ועכשיו אנחנו רואים איך מערך מתנהג בהקשר סקלרי ובהקשר רשימתי.

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

נסתכל עכשיו על מספר דוגמאות נוספות של ביטויים בפרל ואיזה הקשר הם יוצרים.

יצירת הקשר סקלרי

ראינו קודם שלא משנה מה מציבים במשתנה סקלרי, מה שמוצב בו יהיה בהקשר סקלרי. נתאר זאת כך:

$x = SCALAR;

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

$word[3] = SCALAR;

שירשור מצפה למחרוזות משני צידיו, לכן הוא יוצר הקשר סקלרי בשני הצדדים.

"string" . SCALAR;

אבל גם

SCALAR . "string"

ולכן

my @words = ('Foo', 'Bar', 'Baz');
say "Number of elements: " . @words;
say "It is now " . localtime();

ידפיס

Number of elements: 3
It is now Thu Feb 30 14:15:53 1998

אופרטורים נומריים לרוב מצפים לשני מספרים - שני סקלרים - משני צידיהם. מכאן שאופרטורים נומריים יוצרים הקשר סקלרי משני צידיהם:

5 + SCALAR;

SCALAR + 5;

יצירת הקשר רשימתי

קיימות צורות קוד שיוצרות הקשר רשימתי:

אחת מהן היא הצבה למערך:

@x = LIST;

עוד אחת היא הצבה לרשימה:

($x, $y) = LIST;

אפילו אם לרשימה יש רק אלמנט אחד:

($x) =  LIST;

זה מביא אותנו לנושא חשוב שעלול להכשיל אנשים בקלות:

מתי הסוגריים חשובים?

use strict;
use warnings;
use 5.010;

my @words = ('Foo', 'Bar', 'Baz');

my ($x) = @words;
my $y   = @words;

say $x;
say $y;

הפלט הוא:

Foo
3

זהו אחד מאותם מקומות שבהם הסוגריים הם מאוד חשובים.

בהצבה הראשונה my ($x) = @words; הצבנו לרשימה של משתנה(/משתנים) סקלריים. כתוצאה מכך נוצר הקשר רשימתי בצד ימין. כלומר ההערכים של המערך הועתקו לרשימה בצד שמאל של ההצבה. כיוון שהיה רק סקלר אחד, האלמנט הראשון של המערך הועתק, והשאר לא הועתקו.

בהצבה השנייה my $y = @words; הצבנו ישירות למשתנה סקלרי. התוצאה של ההצבה הייתה יצירת הקשר סקלרי בצד ימין של ההצבה. מערך בהקשר סקלרי מחזיר את מספר האלמנטים במערך.

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

אילוץ הקשר סקלרי

גם print() וגם say()יוצרים הקשר רשימתי לפרמטרים שלהם. אז מה עושים אם רוצים להדפיס את מספר האלמנטים במערך? מה עושים אם רוצים להדפיס את התאריך בפורמט היפה שמוחזר על ידי localtime()?

ננסה את הדבר הבא:

use strict;
use warnings;
use 5.010;

my @words = ('Foo', 'Bar', 'Baz');

say @words;
say localtime();

והפלט הוא:

FooBarBaz
3542071011113100
את השורה הראשונה אפשר עוד לקרוא איכשהו, אילו הערכים מצופפים יחד.

השורה השנייה נראית מבלבלת. זה לא נראה אותו דבר כמו התוצאה שציפינו מהפונקציה time() . למעשה אילו תשעה המספרים המוחזרים על ידי הפונקציה localtime() בהקשר רשימתי. אם אתם לא זוכרים, עיינו שוב בפרק על שנת 19100.

הפתרון הוא להשתמש בפונקציה scalar() היוצרת הקשר סקלרי לפרמטר שלה. למעשה זה התפקיד היחיד של הפונקציה scalar() . אנשים רבים רואים בזה מעין (casting) המרה מרבים ליחיד. נראה לי ש-casting היא מילה שאינה בשימוש נפוץ בעולם הפרל.

say scalar @words;
say scalar localtime();

והפלט יהיה:

3
Mon Nov  7 21:02:41 2011

אורך או גודל של מערך בפרלl

בקיצור, אם אתם רוצים לקבל את גודלו של מערך בפרל, אתם יכולים להשתמש בפונקציה scalar() כדי לאלץ את המערך להקשר סקלרי ולהחזיר את גודל המערך.

השיטה המתחכמת

ייתכן שתיראו קוד שנראה כך:

0 + @words;

זוהי בעצם שיטה מתחכמת, לקבל את גודלו של מערך. האופרטור + יוצר הקשר סקלרי בשני צידיו. בהקשר סקלרי המערך מחזיר את גודלו. הוספת 0 למספר שהתקבל אינה משנה את המספר, לכן הביטוי מחזיר את גודלו של המערך.

אני ממליץ לכתוב את זה עם הפונקציה scalar, זה קצת יותר ארוך, אבל זה גם יותר ברור.