# מ־Python ל־Perl אתם מכירים את Python. אתם כותבים list comprehensions בשנתכם, אתם פונים אל `dict` בלי לחשוב, ו־`for x in xs:` הוא זיכרון שרירי. המדריך הזה ממפה כל אחד מההרגלים האלה אל Perl, כך שתוכלו להיות יצרניים ב־`pperl` תוך אחר צהריים אחד במקום ללמוד מחדש תכנות מאפס. שני זעזועים נוחתים בחמש הדקות הראשונות, אז הכירו אותם עכשיו: - **Perl משתמשת בסוגריים מסולסלים ובנקודה־פסיק, לא בהזחה.** אין רווח לבן משמעותי. בלוק הוא `{ ... }`; משפט מסתיים ב־`;`. הזיחו לשם השפיות שלכם, אבל המנתח מתעלם מכך. - **משתנים עוטים sigils.** סקלר הוא `$x`, מערך הוא `@x`, hash הוא `%x`. ה־sigil הוא חלק מהאופן שבו אתם קוראים את המשתנה, לא רק שמו. זהו ההבדל השטחי הגדול ביותר מ־Python, וחלק ראשון אינו עוסק בשום דבר אחר. Every example here runs on `pperl`, a Rust reimplementation of Perl 5.42. Each Perl snippet was executed on `pperl`; the `# ...` comments show its real output. Start your scripts with: ```perl use v5.42; ``` השורה האחת הזו מפעילה את `strict` (ללא משתנים גלובליים בשוגג), את `warnings`, את הפונקציה המובנית `say` (זהו `print` עם תו שורה חדשה בסופו, כמו `print` של Python), חתימות של תת־שגרות, ואת מערכת התכונות המודרנית המשמשת לאורך כל המדריך הזה. ## כיצד לקרוא את זה - [משתנים ו־sigils]() - המעבר בין `$`/`@`/`%`. - [מחרוזות]() - שִחלוף ושרשור. - [מספרים]() - טיפוס שטחי אחד, חלוקה צפה. - [מערכים ורשימות]() - ה־`list` שלכם, בתוספת `map`/`grep`. - [Hashים]() - ה־`dict` שלכם. - [הקשר]() - המושג שאין ל־Python מילה עבורו. קראו את זה. - [אמיתות]() - מה נחשב לשקר, עם הפתעות. - [בקרת זרימה]() - `if`, לולאות, הצורות הסופיתיות. - [תת־שגרות]() - `def` הופך ל־`sub`. - [הפניות]() - נתונים מקוננים ו־closures. - [ביטויים רגולריים]() - regex כתחביר, לא כספרייה. - [קלט/פלט של קבצים וזרמים]() - `open`, קריאות שורה, slurp. - [מודולים וחבילות]() - `import` הופך ל־`use`. - [אובייקטים]() - תחביר ה־`class` המודרני. - [טיפול בשגיאות]() - `try`/`except` הופך ל־`eval` או ל־`try`/`catch`. - [ניבים]() - שורות־היחיד היומיומיות. - [מלכודות בהגעה מ־Python]() - סרקו לפני שאתם כותבים. ## משתנים ו־sigils ב־Python שם פשוט נותן שם לערך. ב־Perl ה**sigil מספר לכם את הצורה**: `$` עבור ערך יחיד, `@` עבור רשימה מסודרת, `%` עבור מיפוי מפתח/ערך. `my` מצהיר על משתנה בעל היקף לקסיקלי, המקבילה ב־Perl לקישור מקומי רגיל. ```python name = "Ada" langs = ["Python", "Perl"] ages = {"Ada": 36, "Linus": 56} ``` ```perl use v5.42; my $name = "Ada"; my @langs = ("Python", "Perl"); my %ages = (Ada => 36, Linus => 56); say $name; # Ada say $langs[0]; # Python say $ages{Ada}; # 36 ``` המלכודת: כשאתם נשלחים *לתוך* צבר כדי לקבל איבר אחד, ה־sigil עוקב אחר הערך שאתם מקבלים בחזרה, לא אחר המכל. איבר יחיד של `@langs` הוא סקלר, ולכן הוא `$langs[0]`, לא `@langs[0]`; ערך אחד מתוך `%ages` הוא `$ages{Ada}`. צורת ה־`@`/`%` היא האוסף כולו; צורת ה־`$` היא חלק אחד ממנו. ## מחרוזות מירכאות כפולות משחלפות משתנים, מירכאות בודדות אינן עושות זאת. אין f-string כי המחרוזת שבברירת המחדל *היא* f-string. שרשור הוא `.`, לא `+` (השמור למספרים). ```python name = "Ada" greeting = f"Hello, {name}" shout = "AB" * 3 ``` ```perl use v5.42; my $name = "Ada"; my $greeting = "Hello, $name"; # Hello, Ada my $literal = 'Hello, $name'; # Hello, $name (no interpolation) my $joined = "AB" . "CD"; # ABCD my $shout = "AB" x 3; # ABABAB ``` המלכודת: שכפול מחרוזת הוא `x`, לא `*`, ואופרטור החיבור הוא `.`, לא `+`. בלבול ביניהם הוא טעות הכתיב הנפוצה ביותר ביום הראשון של מפתח Python. גם איברי מערך וערכי hash משוחלפים בתוך מירכאות כפולות: `"First: $langs[0]"` עובד כפי שנכתב. ## מספרים ל־Perl יש טיפוס מספרי אחד ברמת השטח; אינכם מצהירים על `int` מול `float`. חלוקה תמיד מייצרת float, בדיוק כמו ב־Python 3. ```python print(7 / 2) # 3.5 print(7 // 2) # 3 print(2 ** 10) # 1024 print(10 % 3) # 1 ``` ```perl use v5.42; say 7 / 2; # 3.5 say int(7 / 2); # 3 say 2 ** 10; # 1024 say 10 % 3; # 1 ``` המלכודת: אופרטורי ההשוואה והשוויון מגיעים בשתי משפחות, ואתם בוחרים לפי *טיפוס האופרנדים*, לא לפי זה של המשתנים. מספרים משתמשים ב־`==`, `!=`, `<`, `>`, `<=>`; מחרוזות משתמשות ב־`eq`, `ne`, `lt`, `gt`, `cmp`. `"10" == "10.0"` הוא אמת (מספרי), אבל `"10" eq "10.0"` הוא שקר (מחרוזת). שימוש ב־`==` על מחרוזות, או ב־`eq` על מספרים, הוא באג תכוף ושקט. ## מערכים ורשימות מערך של Perl הוא ה־`list` של Python שלכם. הפעלים משונים בשמם אבל הפעולות זהות, ואינדקסים שליליים עובדים כפי שאתם מצפים. ```python nums = [1, 2, 3, 4, 5] nums.append(6) last = nums.pop() print(len(nums)) # 5 print(nums[1:3]) # [2, 3] ``` ```perl use v5.42; my @nums = (1, 2, 3, 4, 5); push @nums, 6; my $last = pop @nums; # 6 say scalar @nums; # 5 say "@nums[1,2]"; # 2 3 (a slice) ``` Comprehensions הופכים ל־`map` ו־`grep`. `map` ממיר (`[f(x) for x in xs]` של Python); `grep` מסנן (`[x for x in xs if p(x)]` של Python). `$_` הוא האיבר הנוכחי, משתנה הלולאה המובלע של Perl. ```python squares = [x * x for x in nums] evens = [x for x in nums if x % 2 == 0] desc = sorted(nums, reverse=True) ``` ```perl use v5.42; my @nums = (1, 2, 3, 4, 5); my @squares = map { $_ * $_ } @nums; # 1 4 9 16 25 my @evens = grep { $_ % 2 == 0 } @nums; # 2 4 my @desc = sort { $b <=> $a } @nums; # 5 4 3 2 1 ``` המלכודת: `sort` משווה כמחרוזות כברירת מחדל, כך ש־`sort (10, 9, 100)` נותן `10 100 9`. עבור מספרים עליכם להעביר משווה: `sort { $a <=> $b } @nums`. `$a` ו־`$b` הם שני האיברים המושווים, ו־`<=>` הוא אופרטור התלת־כיווני המספרי (`cmp` הוא אחיו של המחרוזות). ## האשים hash של Perl הוא ה־`dict` של Python שלכם. מוצהר עם `%`, ניגשים אליו ערך אחד בכל פעם עם `$h{key}`. ```python h = {"apple": 3, "pear": 5, "plum": 2} print(h["apple"]) # 3 print(sorted(h.keys())) # ['apple', 'pear', 'plum'] print("pear" in h) # True del h["plum"] for k in sorted(h): print(k, "=>", h[k]) ``` ```perl use v5.42; my %h = (apple => 3, pear => 5, plum => 2); say $h{apple}; # 3 say join ",", sort keys %h; # apple,pear,plum say exists $h{pear} ? "yes" : "no"; # yes delete $h{plum}; for my $k (sort keys %h) { say "$k => $h{$k}"; } ``` המלכודת: בדיקת חברוּת היא `exists $h{key}`, לא ה־`in` של Python, והפסיק השמן `=>` הוא מפריד המפתח/ערך הניבי. `=>` גם מצטט אוטומטית את ה־bareword שמשמאלו, כך ש־`apple => 3` אינו זקוק למירכאות סביב `apple`. ל־hash אין סדר; עברו `sort keys %h` כשאתם רוצים סדר יציב. ## הקשר זהו הפרק שכדאי לקרוא פעמיים. ל־Python אין מקבילה, וכמעט כל סיפור ”Perl מוזרה“ מתחקה בחזרה אליו. כל ביטוי ב־Perl רץ או ב**הקשר רשימה** או ב**הקשר סקלר**, הנקבע לפי המקום שבו הוא מופיע, לא לפי מה שהוא. אותו מערך עצמו מתנהג אחרת בכל אחד מהם. השמה של מערך אל *סקלר* נותנת את אורכו; השמה שלו אל *רשימה* (קבוצת משתנים בסוגריים) מעתיקה איברים. ```perl use v5.42; my @list = (10, 20, 30); my $count = @list; # scalar context -> 3 (the length) say $count; # 3 my ($first) = @list; # list context -> first element copied say $first; # 10 my ($a, $b) = @list; # 10 and 20 say "$a $b"; # 10 20 ``` הסוגריים שמשמאל הם כל ההבדל. `my $x = @list` שואל ”כמה?“ ומקבל `3`. `my ($x) = @list` שואל ”תן לי את האיברים“ ומקבל `10`. מפתח Python קורא את שניהם כ“השם את הרשימה“, וזו בדיוק המלכודת. תת־שגרה יכולה לשאול באיזה הקשר היא נקראה, באמצעות `wantarray`, ולהחזיר דברים שונים בהתאם: ```perl use v5.42; sub items { return wantarray ? (1, 2, 3) : "three items"; } my @got = items(); # list context my $msg = items(); # scalar context say "@got"; # 1 2 3 say $msg; # three items ``` פונקציות מובנות משתמשות בזה גם כן. `scalar @array` מאלץ הקשר סקלר כדי לקבל מניין; התאמת regex עם `/g` מחזירה את רשימת ההתאמות בהקשר רשימה ואמת/שקר בהקשר סקלר. הניב הקלאסי ל“מנה את ההתאמות“ מאלץ השמת רשימה בהקשר סקלר באמצעות הצורה הקרויה *countof*: ```perl use v5.42; my $n = () = "a1b2c3" =~ /\d/g; say $n; # 3 ``` המלכודת: אין תשובה יחידה ל“מה המערך הזה עושה“ - זה תלוי בביטוי הסובב. כשמשהו מחזיר מספר שציפיתם שיהיה רשימה (או להפך), ההקשר הוא החשוד הראשון. פנו אל `scalar` כדי לאלץ מניין, ואל סוגריים משמאל כדי לאלץ העתקת איברים. ## אמיתיוּת ערכי השקר של Perl הם רשימה קצרה וספציפית: המספר `0`, המחרוזת הריקה `""`, המחרוזת `"0"`, ו־`undef` (ה־`None` של Perl). **כל השאר הוא אמת** - וזה כולל כמה מחרוזות שמפתח Python מניח שהן שקריות. ```perl use v5.42; for my $v (0, 1, "", "0", "00", "0.0", "false") { say "'$v' is ", ($v ? "true" : "false"); } ``` זה מדפיס, בדיוק: ```text '0' is false '1' is true '' is false '0' is false '00' is true '0.0' is true 'false' is true ``` המלכודת: `"00"` ו־`"0.0"` הם **אמת** ב־Perl, אף שהם נראים אפס מספרית, מפני שרק המחרוזת המדויקת `"0"` היא שקר. המחרוזת `"false"` היא אמת (זוהי מחרוזת לא־ריקה ולא־`"0"`). ובניגוד ל־Python, מערך ריק או hash ריק אינו בעצמו *ערך* שקרי - בהקשר בוליאני מערך מניב את אורכו, כך ש־`if (@list)` הוא אמת כשהרשימה אינה ריקה, וזו הבדיקה שאתם רוצים. עבור בחירת ”השתמש בזה אם מוגדר, אחרת ברירת מחדל“, השתמשו ב־defined-or `//`, שנופל לערך החלופי רק על `undef` (לא על `0` או `""`): ```perl use v5.42; my %cfg = (host => "localhost"); my $port = $cfg{port} // 8080; # key absent -> undef -> 8080 say $port; # 8080 ``` ## זרימת בקרה מילות המפתח מוכרות; האיות נבדל. `elif` הוא `elsif`, ואין `:` ואין הזחה - בלוקים מוקפים בסוגריים מסולסלים. ```python if n < 0: sign = "neg" elif n == 0: sign = "zero" else: sign = "pos" for x in nums: print(x) while running: step() ``` ```perl use v5.42; my $sign; if ($n < 0) { $sign = "neg" } elsif ($n == 0) { $sign = "zero" } else { $sign = "pos" } for my $x (@nums) { say $x } while ($running) { step() } ``` Perl מוסיפה שני דברים שאין ל־Python. **משני סופית** מאפשרים למשפט פשוט לשאת עליו את התנאי או הלולאה שלו עצמו, מה שנקרא בטבעיות עבור שורות־יחיד: ```perl use v5.42; say $_ for @nums; # loop, one statement say "negative" if $n < 0; # guarded statement $sum += $_ for @nums; # accumulate ``` ו־`unless`/`until` הם הצורות השליליות של `if`/`while`, למקרים שבהם הניסוח החיובי נקרא במגושמות: `say "ok" unless $error`. המלכודת: האופרטור התלת־איברי משתשר באותו אופן כמו של Python, אבל עם `?`/`:`, לא `if`/`else`: `my $sign = $n < 0 ? "neg" : $n == 0 ? "zero" : "pos"`. ה־`?:` בסגנון C הוא הניב; אין צורת `x if c else y`. ## תת־שגרות `def` הופך ל־`sub`. ל־Perl המודרנית יש חתימות שנראות מאוד כמו רשימות הפרמטרים של Python, כולל ערכי ברירת מחדל. ```python def greet(name, greeting="Hello"): return f"{greeting}, {name}!" def total(*nums): return sum(nums) ``` ```perl use v5.42; sub greet ($name, $greeting = "Hello") { return "$greeting, $name!"; } say greet("Ada"); # Hello, Ada! say greet("Linus", "Hi"); # Hi, Linus! sub total (@nums) { my $sum = 0; $sum += $_ for @nums; return $sum; } say total(1, 2, 3, 4); # 10 ``` ארגומנטים על שם מילת מפתח ממופים לפרמטר hash, מאחר שזוגות `key => value` משתטחים לרשימה שחתימת `%opts` אוספת: ```perl use v5.42; sub connect_to (%opts) { return "host=$opts{host} port=$opts{port}"; } say connect_to(host => "localhost", port => 8080); # host=localhost port=8080 ``` המלכודת: תת־שגרה מחזירה את ערך הביטוי האחרון שלה גם בלי `return`, וההחזרה היא **רגישת־הקשר** (ראו [הקשר]()). אם תכתבו `return @list`, הקורא מקבל את הרשימה בהקשר רשימה אבל את *המניין* בהקשר סקלר. היו מכוונים לגבי מה שאתם מחזירים כשהוא עשוי לשמש בכל אחת מהדרכים. ## הפניות המערכים וה־hashים של Perl אינם מקננים ישירות; אתם מקננים אותם דרך **הפניות**, שהן המקבילה ב־Perl לידיות האובייקטים של Python (ב־Python כל מכל הוא כבר הפניה, ולכן הצעד הזה בלתי נראה לכם שם). הפניה היא סקלר המצביע אל צבר. קחו אותה עם `\`, עקבו אחריה עם `->`. ```python data = {"name": "Ada", "langs": ["Perl", "Python"]} print(data["langs"][1]) # Python data["langs"].append("Ruby") ``` ```perl use v5.42; my $data = { name => "Ada", langs => ["Perl", "Python"] }; say $data->{name}; # Ada say $data->{langs}[1]; # Python push $data->{langs}->@*, "Ruby"; # postfix deref to push say "@{$data->{langs}}"; # Perl Python Ruby ``` `{ ... }` בונה הפניית hash אנונימית ו־`[ ... ]` הפניית מערך אנונימית - אבני הבניין הליטרליות של נתונים מקוננים, התואמות את הליטרלים `{}` ו־`[]` של Python. החץ `->` עוקב אחר הפניה צעד אחד; בין שני מנויים הוא רשות, כך ש־`$data->{langs}[1]` ו־`$data->{langs}->[1]` זהים. תת־שגרות אנונימיות הן closures, בדיוק כמו ה־`lambda` של Python אבל בלי הגבלת הביטוי היחיד: ```perl use v5.42; my $double = sub ($n) { $n * 2 }; say $double->(21); # 42 ``` המלכודת: צורות ה־deref הסופיתיות (`->@*`, `->%*`, `->$*`) הן הדרך המודרנית והקריאה לבצע dereference לצבר שלם, ו־`"@{ ... }"` הוא האופן שבו אתם משחלפים מערך מ־dereferenced אל מחרוזת. הצורות הישנות יותר `@$ref` ו־`${$ref}{key}` עדיין עובדות ומופיעות בקוד קיים, אבל פנו אל צורות החץ והסופית בקוד חדש. ## ביטויים רגולריים ב־Python ה־regex הוא הספרייה `re`. ב־Perl הוא **תחביר**: `=~` קושר תבנית למחרוזת, `m//` מתאים, `s///` מציב. קבוצות לכידה נוחתות ב־`$1`, `$2`, ולכידות על שם ב־`%+`. ```python import re m = re.search(r"(\d{4})-(\d{2})-(\d{2})", s) if m: year, month, day = m.groups() t = re.sub(",", ";", "a,b,c") parts = "one,two,three".split(",") ``` ```perl use v5.42; my $s = "2026-06-20"; if ($s =~ /(\d{4})-(\d{2})-(\d{2})/) { say "$1 $2 $3"; # 2026 06 20 } if ($s =~ /(?\d{4})/) { say $+{year}; # 2026 } (my $t = "a,b,c") =~ s/,/;/g; # a;b;c my @parts = split /,/, "one,two,three"; # one two three ``` התאמת `/g` בהקשר רשימה מחזירה את *כל* הלכידות, וזו המקבילה הישירה של `re.findall`: ```perl use v5.42; my @nums = "x1y2z3" =~ /(\d)/g; # 1 2 3 say "@nums"; ``` המלכודת: `s///` משנה את היעד שלו *במקום* ומחזיר את מספר ההצבות, לא מחרוזת חדשה. בגלל זה הדוגמה מעתיקה תחילה עם `(my $t = "a,b,c")` ואז מציבה על העותק - אחרת הייתם עורכים ליטרל מחרוזת. כדי לקבל מחרוזת חדשה בלי לגעת במקור, השתמשו בדגל `/r`: `my $t = $s =~ s/,/;/gr`. ## קלט/פלט של קבצים וזרמים הניב הוא ה־`open` בעל שלושת הארגומנטים עם ידית קובץ לקסיקלית, המקבילה הישירה של `with open(...) as f:` של Python. אופרטור הסוגריים המשולשים `<$fh>` קורא שורה, בתפקיד זהה למעבר על אובייקט קובץ של Python. ```python with open("/tmp/sample.txt", "w") as f: for i in range(1, 4): f.write(f"line {i}\n") with open("/tmp/sample.txt") as f: for line in f: print("got:", line.rstrip()) ``` ```perl use v5.42; my $path = "/tmp/sample.txt"; open my $wh, '>', $path or die "cannot write: $!"; print {$wh} "line $_\n" for 1 .. 3; close $wh; open my $rh, '<', $path or die "cannot read: $!"; while (my $line = <$rh>) { chomp $line; say "got: $line"; # got: line 1 ... got: line 3 } close $rh; ``` כדי לבלוע את כל השורות בבת אחת, קראו את הידית בהקשר רשימה: ```perl use v5.42; open my $fh, '<', "/tmp/sample.txt" or die $!; my @lines = <$fh>; # all lines, including newlines say scalar @lines; # 3 ``` המלכודת: שורה הנקראת עם `<$fh>` שומרת על תו השורה החדשה שבסופה; קראו ל־`chomp` כדי להסירו (רפלקס ה־`line.rstrip()` של Python). ו־`open` מחזיר שקר בכישלון במקום לזרוק, ולכן הניב `or die "...: $!"` הוא חובה - `$!` הוא הודעת שגיאת המערכת, ה־`errno` של Perl. ## מודולים וחבילות `import` הופך ל־`use`. מפריד מרחב השמות הוא `::`, לא `.`, ומודול `Foo::Bar` שוכן ב־`Foo/Bar.pm` על נתיב ההכללה `@INC` (ה־`sys.path` של Perl). רשימת הייבוא של מודול היא בחירה של שמות, בדומה מאוד ל־`from module import name`. ```python from math import sqrt import json data = json.loads(text) ``` ```perl use v5.42; use List::Util qw(sum0 max first); say sum0(1 .. 10); # 55 say max(3, 7, 2); # 7 say first { $_ % 2 == 0 } (1, 3, 4, 5); # 4 ``` הספרייה הסטנדרטית גדולה, והרבה ממה שלשמו הייתם פונים ל־PyPI מגיע במובנה או ב־CPAN, ארכיון החבילות של Perl. `List::Util`, `Scalar::Util`, `POSIX`, `File::Spec`, ו־`Data::Dumper` הם היומיומיים. המלכודת: `use` רץ ב *זמן ההידור*, לא בנקודה בקובץ שבה הוא מופיע, ולכן סדר שורות ה־`use` ביחס לקוד שלכם אינו משנה כפי שמיקום `import` משנה. הייבוא גם הוא הצטרפות־מרצון לכל שם: `use List::Util qw(sum0 max)` מביא בדיוק את `sum0` ו־`max` אל מרחב השמות שלכם, ולא יותר. ## אובייקטים עבור קוד חדש, ל־Perl 5.42 יש תחביר `class` ממדרגה ראשונה שייראה מוכר בהגעה מ־Python. שדות מוצהרים עם `field`, מתודות עם `method`, ו־`$self` זמין בתוך כל מתודה בדיוק כפי ש־`self` זמין ב־Python (אינכם מציינים אותו כפרמטר). ```python class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def to_string(self): return f"({self.x}, {self.y})" def move(self, dx, dy): self.x += dx self.y += dy return self p = Point(x=3, y=4) print(p.to_string()) # (3, 4) p.move(1, 1) print(p.to_string()) # (4, 5) ``` ```perl use v5.42; use feature 'class'; class Point { field $x :param = 0; field $y :param = 0; method to_string { return "($x, $y)" } method move ($dx, $dy) { $x += $dx; $y += $dy; return $self; } } my $p = Point->new(x => 3, y => 4); say $p->to_string; # (3, 4) $p->move(1, 1); say $p->to_string; # (4, 5) ``` הבנאי נוצר עבורכם: `:param` מסמן שדה שה־`new` הבנוי־אוטומטית מקבל כארגומנט על שם, ו־`= 0` הוא ברירת המחדל שלו. הורשה היא `:isa`: ```perl use v5.42; use feature 'class'; class Point3D :isa(Point) { field $z :param = 0; method z { return $z } } my $q = Point3D->new(x => 1, y => 2, z => 3); say $q->to_string, " z=", $q->z; # (1, 2) z=3 ``` המלכודת: תכונת ה־`class` עדיין מסומנת כניסיונית ב־Perl 5.42, ועל `pperl` הודעות ”class is experimental“ מודפסות אל **stderr** אפילו עם `no warnings 'experimental::class'` בהיקף. הן אינן נוגעות בפלט התוכנית שלכם, ולכן סקריפט המדפיס אל stdout מתנהג בדיוק כפי שמוצג למעלה; פשוט צפו להודעות בזרם השגיאות. עבור מודל האובייקטים הישן יותר מבוסס ה־`bless` שתפגשו בקוד קיים, ועבור roles, פרטי הורשה, והגירה, ראו את [מדריך התכנות מונחה־העצמים](../oop/index.md). ## טיפול בשגיאות ל־`try`/`except` של Python יש שתי מקבילות. הקלאסית עוטפת קוד ב־`eval { }` ובוחנת את `$@` (השגיאה שנתפסה) לאחר מכן: ```python try: risky(-1) except Exception as e: print("caught:", e) ``` ```perl use v5.42; my $result = eval { risky(-1) }; if ($@) { print "caught: $@"; # caught: negative! } ``` הצורה המודרנית היא `try`/`catch`, הנקראת כמעט בדיוק כמו זו של Python: ```perl use v5.42; use feature 'try'; try { risky(-4); } catch ($e) { print "caught: $e"; # caught: negative! } ``` כאשר הצד הזורק הוא `die`: ```perl use v5.42; sub risky ($n) { die "negative!\n" if $n < 0; return sqrt $n; } ``` המלכודת: `die` עם מחרוזת המסתיימת ב־`\n` מייצר בדיוק את ההודעה הזו; `die` עם מחרוזת ש *אינה* מסתיימת בתו שורה חדשה מקבל `" at SCRIPT line N.\n"` מצורף אוטומטית. סיימו את מחרוזות השגיאה שלכם ב־`\n` כשאתם רוצים הודעה נקייה, והשמיטו זאת כשאתם רוצים את עקבת הקובץ־והשורה. שימו לב גם לשני משתני השגיאה: `$@` הוא החריגה האחרונה שנתפסה (`except ... as e` של Python), בעוד `$!` הוא שגיאת ה *מערכת* האחרונה (`open` שנכשל, מחרוזת ה־`errno`). ## ניבים כמה דפוסים שתראו מדי יום ותרצו באצבעות שלכם. מיון רשימה לפי מפתח מחושב (טרנספורם שוורץ - ה־`sorted(xs, key=f)` של Python בעבודת יד, קישוט ואז מיון ואז הסרת קישוט): ```perl use v5.42; my @words = qw(apple fig pear); my @by_length = map { $_->[1] } sort { $a->[0] <=> $b->[0] } map { [ length $_, $_ ] } @words; say "@by_length"; # fig pear apple ``` בניית hash מרשימה, מקבילת ה־dict-comprehension (`{w: len(w) for w in words}`): ```perl use v5.42; my @words = qw(apple pear fig); my %len = map { $_ => length $_ } @words; say "$_ => $len{$_}" for sort keys %len; # apple => 5 # fig => 3 # pear => 4 ``` ו־`pperl` הוא כלי שורת־פקודה בנישה של `awk`/`sed`. שורת־היחיד עם הלולאה המובלעת היא הרפלקס היומיומי של מפתח Perl: ```bash pperl -lane '$s += $F[-1]; END { print $s }' data.txt ``` המלכודת: קראו את [מדריך שורות־היחיד](../oneliner/index.md) עבור המתגים (`-n`, `-p`, `-a`, `-l`, `-e`) ועשרות המתכונים הבנויים עליהם; זהו אחד הדברים בעלי המנוף הגבוה ביותר ללמוד בהגעה מרקע של shell ו־Python. ## מלכודות בהגעה מ־Python המלכודות, אסופות לסריקה אחרונה לפני שאתם מתחילים לכתוב: - **Sigils משתנים עם השימוש.** איבר אחד של `@a` הוא `$a[0]`; ערך אחד של `%h` הוא `$h{k}`. sigil המכל ו־sigil האיבר נבדלים. - **`.` מצרף מחרוזות, `+` מחבר מספרים.** לעולם אל תשתמשו ב־`+` כדי לשרשר שתי מחרוזות; זה כופה עליהן המרה למספרים ומזהיר. - **שתי משפחות השוואה.** `==`/`<`/`<=>` למספרים, `eq`/`lt`/ `cmp` למחרוזות. בחרו לפי טיפוס האופרנד, לא לפי המשתנה. - **`sort` ממוין כמחרוזות כברירת מחדל.** העבירו `{ $a <=> $b }` לסדר מספרי. - **הקשר.** `my $x = @a` הוא *האורך*; `my ($x) = @a` הוא *האיבר הראשון*. הסוגריים הם כל ההבדל. קראו מחדש את [הקשר]() כשערך חוזר בצורה הלא־נכונה. - **הפתעות אמיתות.** `"0"` הוא שקר, אבל `"00"` ו־`"0.0"` הם **אמת**. רק `0`, `""`, `"0"`, ו־`undef` הם שקר. - **`s///` עורך במקום** ומחזיר מניין; השתמשו בדגל `/r` כדי לקבל מחרוזת חדשה במקום זאת. - **`open` אינו זורק.** השתמשו ב־`open ... or die "...: $!"`. - **הריצו `chomp` על קריאות השורה שלכם.** `<$fh>` שומר על תו השורה החדשה שבסוף. - **מקור שאינו ASCII זקוק ל־`use utf8;`.** תחת `use v5.42;` בית שאינו ASCII כליטרל במקור שלכם הוא שגיאת הידור בלעדיו. שמרו על נתוני מחרוזות כ־ASCII אלא אם תוסיפו במפורש `use utf8;`. - **The `class` feature prints experimental notices to stderr** on `pperl`. Correct output, noisy error stream.