אופרטורי השמה#
השמה רגילה בתוספת הצורות המורכבות - לכל אופרטור בינארי המייצר ערך יש גם צורת השמה מורכבת שמיישמת את הפעולה במקום.
= רגיל#
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
מפוענח:
$string =~ /\d/gבהקשר רשימה מניב את כל לכידות הספרות.() = ...היא השמת רשימה לרשימה הריקה (אינה משימה דבר, אך מעריכה את הצד הימני בהקשר רשימה).$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
אופרטור | שקול | שימוש |
|---|---|---|
|
| לצבור |
|
| לחסר במקום |
|
| לשנות קנה־מידה |
|
| לחלק במקום |
|
| מודולו |
|
| להעלות בחזקה במקום |
|
| לצרף (מחרוזת) |
|
| לחזור (מחרוזת), או |
|
| מסיכת ביטים AND-equals |
|
| מסיכת ביטים OR-equals (קביעת ביטים) |
|
| מסיכת ביטים XOR-equals (החלפה) |
|
| היסט שמאלה במקום |
|
| היסט ימינה במקום |
|
| ״לצמצם אם כרגע אמת״ |
|
| ברירת מחדל אם כרגע שקר |
|
| ברירת מחדל אם כרגע 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)מתחלק לעומת היותו רשימה יחידה.