אופרטורי השמה#

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

= רגיל#

my $x = 10;                          # scalar assignment
my @a = (1, 2, 3);                   # list assignment
my ($x, $y, $z) = (1, 2, 3);         # destructuring
my ($first, @rest) = @items;         # one + remainder
my %h = (a => 1, b => 2);            # hash from key-value list

השמה היא אסוציאטיבית לימין - שרשראות מוערכות מימין־לשמאל:

$a = $b = $c = 0;                    # parses as $a = ($b = ($c = 0))
                                     # all three become 0

לביטוי ההשמה כולו יש ערך: בהקשר סקלר זהו הערך המושם; בהקשר רשימה זוהי רשימת האלמנטים שאליהם הושמו ערכים, בסדר משמאל־לימין:

my $count = (my @items = qw(a b c)); # $count = 3
                                     # - number of elements assigned
                                     # to @items, in scalar context

while ((my $line = <$fh>) ne '') { ... }   # uses the assignment as
                                            # both side-effect and value

השמת רשימה בהקשר סקלר#

כנראה הניב הנפוץ ביותר ב־Perl שאיש אינו יכול לצטט את הכלל שלו:

my $n = () = $string =~ /\d/g;       # count digits in $string

מפוענח:

  1. $string =~ /\d/g בהקשר רשימה מניב את כל לכידות הספרות.

  2. () = ... היא השמת רשימה לרשימה הריקה (אינה משימה דבר, אך מעריכה את הצד הימני בהקשר רשימה).

  3. $n = (...) מציב את השמת הרשימה בהקשר סקלר, שמוערך למספר האלמנטים בצד ימין.

תוצאה: $n הוא מספר ההתאמות. אין scalar(grep ...) או פונקציית count מובנית לכך; טריק הרשימה־הריקה הוא הניב הקנוני.

השמה מורכבת#

כל אופרטור בינארי שמתאים לתבנית OP= קיים. המכניקה זהה ל־$x = $x OP $y, פרט לכך ש־$x מוערך פעם אחת בלבד בצד שמאל - מה שמשנה כשל־lvalue יש תופעת־לוואי (למשל autoviv, קריאה לפונקציה):

$h->{counter}++;                     # autoviv $h->{counter}, increment
$h->{counter} += 1;                  # same effect, but spell out the OP

אופרטור

שקול

שימוש

+=

$x = $x + $y

לצבור

-=

$x = $x - $y

לחסר במקום

*=

$x = $x * $y

לשנות קנה־מידה

/=

$x = $x / $y

לחלק במקום

%=

$x = $x % $y

מודולו

**=

$x = $x ** $y

להעלות בחזקה במקום

.=

$x = $x . $y

לצרף (מחרוזת)

x=

$x = $x x $y

לחזור (מחרוזת), או (@) x= n

&=

$x = $x & $y

מסיכת ביטים AND-equals

|=

$x = $x | $y

מסיכת ביטים OR-equals (קביעת ביטים)

^=

$x = $x ^ $y

מסיכת ביטים XOR-equals (החלפה)

<<=

$x = $x << $y

היסט שמאלה במקום

>>=

$x = $x >> $y

היסט ימינה במקום

&&=

$x = $x && $y

״לצמצם אם כרגע אמת״

||=

$x = $x || $y

ברירת מחדל אם כרגע שקר

//=

$x = $x // $y

ברירת מחדל אם כרגע undef

$count    += 5;                      # arithmetic
$path     .= "/user";                # string append
$flags    |= FLAG_VERBOSE;           # set a flag bit
$flags    &= ~FLAG_VERBOSE;          # clear a flag bit
$cache    ||= load_data();           # lazy populate
$cfg{key} //= $default;              # default that respects 0 and ""
$str       x= 3;                     # repeat in place

Lvalues - מה יכול להופיע בצד שמאל#

האופרנד השמאלי של = (או כל צורה מורכבת) חייב להיות lvalue - מיקום שניתן לכתוב אליו. ה־lvalues של Perl כוללים:

  • משתנה סקלר פשוט: $x, $obj->{field}.

  • משתנה מערך או האש: @arr, %h.

  • אלמנט מערך או פרוסה: $arr[3], @arr[1..3].

  • אלמנט האש או פרוסה: $h{key}, @h{qw(a b c)}.

  • מכל שעבר deref: $$ref, @$aref, %{$h}.

  • הצורה המוצהרת ב־local/my של כל אחד מהנ״ל.

  • תת־מחרוזת: substr($s, $offset, $len) = "...".

  • שילוש שהענפים שלו הם lvalues (ראו שילוש).

  • הפסאודו־אופרטורים pos, vec, keys על האשים קשורים, חריצי @_ מסוימים, וכמה צורות מתמחות.

רוב הזמן אתם כותבים lvalue בלי לחשוב. המקרים שבהם אתם עוצרים ובודקים הם אקזוטיים - substr כ־lvalue, שילוש כ־lvalue, פרוסת מערך כיעד של השמת רשימה.

השמת רשימה רבת־יעדים#

הצד הימני מוערך תחילה בהקשר רשימה, ואז מחולק בין ה־lvalues שבצד שמאל. הדבר מקל על החלפה:

($a, $b) = ($b, $a);                 # swap
($x, $y, $z) = ($y, $z, $x);         # rotate left

אם הרשימות שונות באורכן:

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

  • יותר חריצים בצד שמאל מאשר ערכים בצד ימין ← חריצים שלא מולאו הופכים ל־undef.

my ($a, $b) = (1, 2, 3, 4);          # $a=1, $b=2; 3 and 4 dropped
my ($a, $b, $c) = (1, 2);            # $a=1, $b=2, $c=undef

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

my ($head, @tail) = @items;          # $head = first element
                                     # @tail = the rest
my ($head, %tail) = @items;          # if @items has key/value pairs
                                     # after the first

רק מערך או האש אחד בצד שמאל; אחרת לא היה חד־משמעי היכן אחד מסתיים והבא מתחיל.

קדימות#

אופרטורי ההשמה יושבים בשורה 19 - נמוך למדי, רופפים יותר מהשוואה ומ־?:, הדוקים יותר רק מאופרטורי הפסיק ומהלוגיים בצורת־מילה (and, or, not, xor). זו הסיבה ש־my $fh = open ... or die עובד (or רופף אפילו יותר מ־=).

ראו גם#

  • לוגיקה - ||=, //=, &&= הם סוסי־העבודה של ניבי ״ברירת מחדל אם חסר״.

  • מציין־מקום - רוב צורות ה־lvalue כוללות מציין־מקום.

  • פסיק - = מתפענח מתוך רשימת ה־, הסובבת באמצעות קדימות; הבנת שורה 19 מול שורה 20 היא מה שמלמד אתכם מתי (a, b)=(c, d) מתחלק לעומת היותו רשימה יחידה.