# מ־Tcl ל־Perl אתם מכירים את Tcl. אתם כותבים `set x 5`, מבצעים החלפה עם `$x`, נשענים על `[expr {...}]` לביצוע חשבון, בונים רשימות עם `lappend` ועוברים עליהן עם `foreach`, ומכופפים מחרוזות עם `regexp` ו־`regsub`. מדריך זה ממפה כל אחד מההרגלים הללו אל Perl, כך שתוכלו לשמר כל רפלקס שיש לכם ולאמץ את הדברים ש־Tcl מקשה עליהם. ל־Tcl ול־Perl יש אותם שורשים: כתיבת סקריפטים ב־Unix, השקפת־עולם של מחרוזת־תחילה, והחלפת־`$` כדרך להגיע למשתנה. רוב מה שאתם יודעים ממופה כמעט ישירות - ו־Perl נותנת לכם מבני נתונים אמיתיים (`@arrays` ו־`%hashes` כטיפוסים ממדרגה ראשונה, לא רשימות שגויסו לתפקיד) ומערכת מודולים עצומה לנחות בה. שני פריטי חיכוך ספציפיים מקבלים את המשקל במדריך זה: טיפוסי המערך/האש הנפרדים של Perl היכן של־Tcl יש רשימות ומערכים אסוציאטיביים, והביטויים הרגולריים של Perl (על־קבוצה של אלה של Tcl). חומר השורה־בכל־פעם ושורת־הקוד־האחת קל יותר כאן, מכיוון ש־Tcl אינה שפת שורת־קוד־אחת; את זמנכם תבלו במשתנים, נתונים, זרימת בקרה, וביטויים רגולריים. Every runnable example here was executed on `pperl`, a Rust reimplementation of Perl 5.42; the `# ...` comments show its real output. Start scripts with: ```perl use v5.42; ``` שורה אחת זו מפעילה את `strict`, את `warnings`, ואת הפונקציה המובנית `say` (כלומר `print` עם תו שורה חדשה נגרר, התאום הגס של ה־`puts` של Tcl), מערך התכונות המודרני המשמש לאורך כל הדרך. #### NOTE מתגי שורה־אחת ב־build הזה של pperl מתגי שורת־הקוד־האחת של Perl - `perl -ne`, `perl -pe`, `-a`, `-i`, `-l` - הם **perl5 5.42 תקני** והם הצורה האידיומטית לעבודת טקסט אד־הוק. אך משפחת מתגי הלולאה המשתמעת (`-n`, `-p`, `-a`, `-F`, `-i`, `-l`) **עדיין אינה מזוהה על ידי build זה של `pperl`** - רק `-e` מזוהה. לכן דוגמאות שורת־הקוד־האחת שלהלן מוצגות *ללא* פלט, וכל אחת מהן מצומדת לצורת סקריפט־מלא עם לולאה מפורשת (`while (<$fh>) { ... }`) ש**אכן** רצה על `pperl` היום ונושאת את הפלט המאומת. השתמשו בצורת הסקריפט המלא עד שהמתגים ייכנסו. ## כיצד לקרוא את זה - [משתנים והחלפה]() - `set` הופך ל־`my`, `[expr]` נעלם, החלפת `$x` נשארת. - [רשימות ומערכים]() - `lindex`/`lappend`/`lsort` הופכים לפעולות מערך של Perl. - [מערכים אסוציאטיביים והאשים]() - `set a(k) v` הופך ל־`$a{k}`; `dict` הופך להאש. - [פרוצים והפניות]() - `proc` הופך ל־`sub`; `upvar`/`uplevel` הופכים להפניות. - [ביטויים רגולריים והחלפה]() - `regexp`/ `regsub`/`string map` הופכים ל־`m//`/`s///`/`tr///`. - [זרימת בקרה]() - `if`/`while`/`foreach`/`switch` הופכים לאלה של Perl, בתוספת ציטוט `{}` מול `""`. - [לולאת השורה/רשומה]() - קריאת קובץ שורה אחר שורה עם `$_` ו־`$.`. - [שדות ופיצול]() - `split`/`join`, המקבילה ל־`split` של Tcl. - [קלט/פלט, צינורות, ועריכה במקום]() - `open`/`gets`/`puts`/`exec` הופכים ל־`open`/`<$fh>`/`print`/`qx`. - [שורות־קוד־אחת ומתגים]() - `-n`, `-p`, `-e`, נשמר תמציתי. - [מלכודות בהגעה מ־Tcl]() - סרקו לפני שאתם כותבים. ## משתנים והחלפה ב־Tcl, `set x 5` יוצר משתנה ו־`$x` מחליף את ערכו. ב־Perl, `my $x = 5;` מצהיר על משתנה מתוחם מילונית ו־`$x` מחליף אותו - תחביר ההחלפה שאתם כבר מכירים עובר מילולית. ההקלה היא ש־Perl יש לה אופרטורים מולדים: אין `[expr {...}]`. חשבון הוא פשוט חשבון. ```tcl set x 5 set name "world" set sum [expr {$x + 3}] puts "x is $x" puts "sum is $sum" ``` ```perl use v5.42; my $x = 5; # set x 5 my $name = "world"; my $sum = $x + 3; # native operators, no [expr] needed say "x is $x"; # x is 5 say "sum is $sum"; # sum is 8 ``` ציטוט ממופה בנקיות, וזה מיפוי משמח: ה־`"..."` של Tcl (החלפה מתרחשת) הוא מחרוזת מצוטטת־כפול של Perl, וה־`{...}` של Tcl (מילולי, ללא החלפה) הוא מחרוזת מצוטטת־בודד של Perl. ```perl use v5.42; my $name = "world"; say "hello, $name"; # hello, world (interpolates) say 'no $interp here'; # no $interp here (literal) ``` המלכודת: Tcl היא ”הכול הוא מחרוזת“ ו־Perl קרובה לכך - סקלר מומר אוטומטית בין מספר למחרוזת לפי הקשר - אך Perl מפצלת *השוואה* לשתי משפחות אופרטורים, ואתם בוחרים לפי הפעולה, לא לפי הערך. מספרים משתמשים ב־`==`, `!=`, `<`, `>`; מחרוזות משתמשות ב־`eq`, `ne`, `lt`, `gt`. ```perl use v5.42; my $x = "5"; say $x + 3; # 8 (numeric context coerces "5") say $x . "3"; # 53 (string context) say "10" == "10.0" ? "num-equal" : "num-differ"; # num-equal say "10" eq "10.0" ? "str-equal" : "str-differ"; # str-differ ``` `==` משווה את `"10"` ו־`"10.0"` כמספרים (שווים); `eq` משווה אותם כמחרוזות (שונים). שימוש ב־`==` היכן שהתכוונתם ל־`eq`, או להפך, הוא הבאג השקט האחד שהשקפת־העולם של מחרוזת־תחילה מכינה לכם. ## רשימות ומערכים רשימת Tcl היא מערך Perl, והפעלים מתיישרים אחד לאחד. ההסטה הגדולה: ב־Tcl *הכול הוא רשימה*, כולל מחרוזות שאתם מפצלים תוך כדי תנועה; ב־Perl מערך (`@a`) הוא טיפוס נפרד ממדרגה ראשונה עם הסיגיל שלו. כשאתם מגיעים לאיבר אחד, הסיגיל עוקב אחר ה *איבר*, כך שזה `$a[0]` (סקלר), לא `@a[0]`. ```tcl set items [list apple pear fig] puts [lindex $items 0] puts [llength $items] lappend items plum set sorted [lsort $items] foreach it $items { puts "item: $it" } ``` ```perl use v5.42; my @items = ("apple", "pear", "fig"); say $items[0]; # apple (lindex $items 0) say scalar @items; # 3 (llength $items) push @items, "plum"; # lappend items plum my @sorted = sort @items; # lsort say "@sorted"; # apple fig pear plum for my $it (@items) { # foreach it $items say "item: $it"; } ``` ל־`lsearch` - ”מצא את האינדקס של איבר תואם“ - אין פונקציה מובנית יחידה; ה־Perl האידיומטית היא `grep` על טווח האינדקסים, עם `$#items` כאינדקס האחרון: ```perl use v5.42; my @items = ("apple", "pear", "fig", "plum"); my ($idx) = grep { $items[$_] eq "fig" } 0 .. $#items; # lsearch say "fig at $idx"; # fig at 2 ``` המלכודת: `scalar @items` היא הדרך שבה אתם משיגים את האורך (ה־`llength` של Tcl); כתיבת `my $n = @items` עובדת מכיוון שהשמת מערך לסקלר מניבה את ספירתו, אך אייתו זאת `scalar @items` כשאתם רוצים את האורך בתוך ביטוי גדול יותר. ו־`sort` משווה כ *מחרוזות* כברירת מחדל, כך ש־`sort (10, 9, 100)` נותן `10 100 9`; העבירו משווה מספרי `sort { $a <=> $b } @nums` לסדר מספרי, היכן ש־`$a` ו־`$b` הם שני האיברים ו־`<=>` הוא האופרטור המספרי התלת־כיווני. ## מערכים אסוציאטיביים והאשים מערך אסוציאטיבי של Tcl - `set a(red) 1` - הוא האש Perl. גישת האיבר ממופה ישירות: ה־`$a(red)` של Tcl הוא ה־`$a{red}` של Perl, והאוסף כולו הוא `%a` (ל־Tcl אין תחביר למערך כערך יחיד; ל־Perl יש). ה־`dict` של Tcl המודרנית ממופה לאותה האש Perl, או להפניית האש כשאתם זקוקים לקנן או להעביר אותה. ```tcl set a(red) 1 set a(green) 2 set a(blue) 3 puts $a(red) puts [array exists a] foreach k [lsort [array names a]] { puts "$k => $a($k)" } unset a(blue) ``` ```perl use v5.42; my %a = (red => 1, green => 2, blue => 3); say $a{red}; # 1 ($a(red)) say exists $a{green} ? "yes" : "no"; # yes (info exists a(green)) for my $k (sort keys %a) { # array names a say "$k => $a{$k}"; } delete $a{blue}; # unset a(blue) ``` זה מדפיס: ```text 1 yes red => 1 green => 2 blue => 3 ``` המלכודת: חברות היא `exists $a{key}`, לא פקודה נפרדת, והפסיק השמן `=>` הוא מפריד המפתח/ערך האידיומטי בליטרל האש. `=>` גם מצטט אוטומטית את ה־bareword משמאלו, כך ש־`red => 1` אינו זקוק לגרשיים סביב `red`. להאש אין סדר מובנה (גם למערך Tcl אין); עברו `sort keys %a` כשאתם רוצים סדר יציב, בדיוק כפי שאתם נשענים על `lsort [array names a]`. ## פרוצים והפניות `proc name {args} {body}` הופך ל־`sub name { ... }` של Perl. הדרך הקלאסית של Tcl לקרוא ארגומנטים - מיקומית, לפי שם - יש לה תאום Perl ישיר: `my ($a, $b) = @_;` פורק את מערך הארגומנטים `@_`. ל־Perl מודרנית יש גם חתימות, הנקראות כמו רשימת ה־`{args}` של Tcl ומוסיפות ברירות מחדל. ```tcl proc add {a b} { return [expr {$a + $b}] } puts [add 3 4] proc greet {who {greeting Hello}} { return "$greeting, $who!" } puts [greet Tcl] puts [greet Perl Hi] ``` ```perl use v5.42; sub add { my ($a, $b) = @_; # unpack the argument array return $a + $b; } say add(3, 4); # 7 sub greet ($who, $greeting = "Hello") { # signature with default return "$greeting, $who!"; } say greet("Tcl"); # Hello, Tcl! say greet("Perl", "Hi"); # Hi, Perl! ``` ההעברה־לפי־שם של Tcl - `upvar`, שבה פרוצדורה מושיטה יד מעלה ומשנה משתנה של הקורא - הופכת ל**הפניה** של Perl: קחו אחת עם `\`, עקבו אחריה עם `$$ref`. אתם מעבירים את ההפניה במפורש במקום לנקוב את המשתנה, מה שהופך את זרימת הנתונים לגלויה באתר הקריאה. ```perl use v5.42; sub increment { my ($ref) = @_; $$ref++; # mutate through the reference (Tcl: upvar) } my $count = 10; increment(\$count); # pass a reference to $count say $count; # 11 ``` המלכודת: `@_` הוא מערך הארגומנטים, ו־`my ($a, $b) = @_;` *מעתיק* את הארגומנטים למקומיים בעלי שם - השורה שאתם כמעט תמיד רוצים בראש תת־שגרה. נשיאה לכינוי בסגנון `upvar` נדרשת לעיתים רחוקות ב־Perl; כשאתם כן זקוקים לשנות נתוני קורא, העבירו הפניה (`\$x`, `\@arr`, `\%h`) במכוון במקום לכנות לפי שם. הפניות הן גם הדרך שבה Perl מקננת נתונים (מערך של האשים, האש של מערכים); אותו מנגנון המחליף את `upvar` הוא זה המחליף את הרשימות המקוננות המקודדות־מחרוזת של Tcl. ## ביטויים רגולריים והחלפה זה סעיף מטען. ה־`regexp` וה־`regsub` של Tcl משתמשים בביטויים רגולריים מתקדמים; הביטויים הרגולריים של Perl הם **על־קבוצה**, כך שהתבניות שאתם מכירים עוברות וצוברות תכונות. Perl הופכת ביטויים רגולריים ל *תחביר*, לא לפקודה: `=~` קושר תבנית למחרוזת, `m//` מתאים, `s///` מחליף, ו־`tr///` מתעתק. ```tcl set s "order 42 shipped" if {[regexp {(\d+)} $s -> num]} { puts "number: $num" } set t [regsub -all {o} "foo boo zoo" O] puts $t set u [string map {a A b B} "abcabc"] puts $u ``` ```perl use v5.42; my $s = "order 42 shipped"; if ($s =~ /(\d+)/) { # regexp; capture lands in $1 say "number: $1"; # number: 42 } (my $t = "foo boo zoo") =~ s/o/O/g; # regsub -all -> s///g say $t; # fOO bOO zOO (my $u = "abcabc") =~ tr/ab/AB/; # string map (char-for-char) say $u; # ABcABc ``` גם הלכידה ממופה: משתנה ההתאמה `-> num` של Tcl הופך ל־`$1`, `$2` של Perl, וכן הלאה, כשלכודות בעלות שם נוחתות ב־`%+`: ```perl use v5.42; if ("2026-06-21" =~ /(?\d{4})-(?\d{2})/) { say "$+{y} / $+{m}"; # 2026 / 06 } ``` ה־`string match` של Tcl הוא התאמת glob, לא ביטוי רגולרי (`string match *.txt $name`). ב־Perl, עגנו ביטוי רגולרי במקום - `/\.txt$/` היא המקבילה - מכיוון ששפת התבנית האחת של Perl מכסה את שתי המשימות. ```perl use v5.42; my $name = "report.txt"; say "matches" if $name =~ /\.txt$/; # string match *.txt $name # matches ``` המלכודת: `s///` משנה את היעד שלו *במקום* ומחזיר את *ספירת* ההחלפות, לא את המחרוזת החדשה - וזו הסיבה שהדוגמאות לעיל מעתיקות תחילה עם `(my $t = "...")` לפני ההחלפה. כדי לקבל מחרוזת חדשה ולהשאיר את המקור ללא שינוי, השתמשו בדגל `/r`: `my $new = $s =~ s/o/O/gr`. ו־`tr///` (המקבילה ל־`string map` עבור תווים בודדים) **אינו** ביטוי רגולרי: צידו השמאלי הוא קבוצת תווים מילולית, כך ש־`tr/ab/AB/` ממפה את `a` ו־`b` בלבד. לעבודת תבניות, נשענו על `s///`. ## זרימת בקרה מבני הבקרה ממופים כמעט אחד לאחד; האיות מוסט והסוגריים המסולסלים נשארים. ה־`if {cond} {body}` של Tcl הופך ל־`if (cond) { body }` של Perl, `elseif` הופך ל־`elsif`, ו־`foreach` הופך ל־`for` (שני האיותים הם כינויים ב־Perl; `foreach` עובד גם הוא). ```tcl if {$n < 0} { set sign neg } elseif {$n == 0} { set sign zero } else { set sign pos } set i 0 while {$i < 3} { puts "i=$i"; incr i } foreach w {a b c} { puts "w=$w" } ``` ```perl use v5.42; my $n = 0; my $sign; if ($n < 0) { $sign = "neg" } elsif ($n == 0) { $sign = "zero" } # elseif -> elsif else { $sign = "pos" } say $sign; # zero my $i = 0; while ($i < 3) { say "i=$i"; $i++ } # incr i -> $i++ for my $w (qw(a b c)) { say "w=$w" } # foreach w {a b c} ``` ל־`switch` של Tcl אין מילת־מפתח יחידה ב־Perl; ההחלפה האידיומטית היא **האש שיגור** הממפה כל מקרה להפניית קוד, מה שמהיר וגמיש יותר משרשרת `if`: ```perl use v5.42; my $cmd = "start"; my %dispatch = ( start => sub { "starting" }, stop => sub { "stopping" }, ); say $dispatch{$cmd}->(); # starting ``` המלכודת: ההבחנה בין `{}` ל־`""` שעליה אתם נשענים ב־Tcl לדחייה מול החלפה ממופה ל־`''` מול `""` של Perl למחרוזות (שכוסה לעיל), אך הסוגריים המסולסלים של *בלוק* ב־Perl אינם ציטוט - `{ ... }` של Perl לאחר `if`/`while`/`for` הוא בלוק קוד, תמיד מוערך, לעולם לא מחרוזת נדחית. אין שלב של ”הגוף הוא מחרוזת עד שאני מריץ אותו“; Perl מנתחת את הבלוק בזמן ההידור. מתאמי סיומת הם בונוס של־Tcl אין צורה אליו: `say $_ for @items;` ו־`say "neg" if $n < 0;` נושאים את הלולאה או התנאי לאחר המשפט. ## לולאת השורה/רשומה Tcl קוראת קובץ עם `set fh [open f r]; while {[gets $fh line] >= 0} {...}`. המקבילה של Perl היא לולאת `while (<$fh>)`, כשכל שורה נוחתת ב־`$_` (משתנה הנושא המשתמע) או בסקלר בעל שם. מספר השורה נמצא ב־`$.`. ```tcl set fh [open /tmp/tcl_data.txt r] while {[gets $fh line] >= 0} { puts "got: $line" } close $fh ``` ```perl use v5.42; open my $fh, '<', '/tmp/tcl_data.txt' or die "open: $!"; while (my $line = <$fh>) { # gets $fh line chomp $line; # <$fh> keeps the newline; strip it say "got: $line"; # puts } close $fh; # got: apple # got: banana # got: cherry ``` (קובץ הקלט החזיק `apple`, `banana`, `cherry`.) שימוש ב־`$_` ובמונה השורות `$.` נקרא קרוב עוד יותר ללולאת רשומה: ```perl use v5.42; open my $fh, '<', '/tmp/tcl_data.txt' or die "open: $!"; while (<$fh>) { # each line lands in $_ chomp; # chomp defaults to $_ say "$. : $_"; # $. is the current line number } close $fh; # 1 : apple # 2 : banana # 3 : cherry ``` המלכודת: ה־`gets` של Tcl מקצץ עבורכם את תו השורה החדשה הנגרר; ה־`<$fh>` של Perl שומר עליו, לכן קראו ל־`chomp` כשאינכם רוצים אותו. ללא ארגומנט, `chomp` ו־`say`/`print` שניהם משתמשים בברירת המחדל `$_`, וזו הסיבה שהלולאה השנייה לעולם אינה נוקבת את משתנה השורה. ## שדות ופיצול ה־`split $line $sep` של Tcl מחזיר רשימה; ה־`split /sep/, $line` של Perl מחזיר מערך, ו־`join` מחבר אותו בחזרה. ההבדל: מפריד פיצול של Perl הוא *ביטוי רגולרי*, כך שאתם מקבלים את שפת התבנית המלאה בחינם. ```tcl set line "a:b:c" set parts [split $line ":"] puts [llength $parts] puts [lindex $parts 1] puts [join $parts ","] ``` ```perl use v5.42; my $line = "a:b:c"; my @parts = split /:/, $line; # split $line ":" (separator is a regex) say scalar @parts; # 3 (llength $parts) say $parts[1]; # b (lindex $parts 1) say join ",", @parts; # a,b,c (join $parts ",") ``` המלכודת: `split ' '` עם מחרוזת רווח־בודד מילולית הוא מקרה מיוחד המפצל על *כל רצף של רווחים לבנים* ומשמיט שדות ריקים מובילים - התנהגות ”פיצול למילים“ בסגנון awk, ובדרך כלל מה שאתם רוצים לקלט חופשי־צורה. `split / /` (ביטוי רגולרי עם רווח אחד) הוא ה“פיצול על כל רווח בודד“ המילולי ואינו דוחס רצפים. הישענו על `split ' '` כדי לחלק מילים לאסימונים: ```perl use v5.42; my @words = split ' ', " the quick brown "; say "@words"; # the quick brown ``` ## קלט/פלט, צינורות, ועריכה במקום ה־`open`/`gets`/`puts`/`read`/`close` של Tcl ממופים אל ה־`open`/`<$fh>`/ `print`/בליעה/`close` של Perl. הניב הוא ה־`open` התלת־ארגומנטי עם מטפל קובץ מילוני. ה־`exec` של Tcl - הרץ פקודה ולכוד את פלטה - הופך ל־`qx{...}` (גרשים אחוריים) של Perl או ל־`system` כשאינכם זקוקים לפלט. ```tcl set out [exec echo hello from shell] puts "exec said: $out" ``` ```perl use v5.42; my $out = qx{echo hello from shell}; # exec -> qx// (backticks) chomp $out; say "exec said: $out"; # exec said: hello from shell ``` ל־Tcl אין עריכת קובץ במקום מובנית; אתם קוראים, ממירים, וכותבים חזרה. המתג `-i` של Perl הוא צורת שורת־הקוד־האחת של בדיוק זה, והמקבילה הניתנת־להרצה של סקריפט מלא היא קריאה־שינוי־כתיבה שאתם יכולים לכתוב היום: ```perl use v5.42; my $path = '/tmp/tcl_inplace.txt'; # holds: red green blue open my $in, '<', $path or die "read: $!"; my @lines = <$in>; # slurp all lines (list context) close $in; s/e/E/g for @lines; # transform each line's $_ open my $out, '>', $path or die "write: $!"; print {$out} @lines; # write them back close $out; # file now holds: # rEd # grEEn # bluE ``` המלכודת: `open` מחזיר שקר בכישלון במקום לזרוק חריגה (Tcl זורקת שגיאה שאתם תופסים עם `catch`), לכן הניב `or die "...: $!"` הוא חובה - `$!` היא מחרוזת שגיאת המערכת. לצינורות, Perl פותחת מטפל קובץ של צינור ישירות: `open my $fh, '-|', 'ls', '-l'` קורא את פלט הפקודה ו־`open my $fh, '|-', 'sort'` כותב לקלט הפקודה, הצורה המובנית של ה־`open "|command"` של Tcl. ## שורות־קוד־אחת ומתגים Tcl אינה שפת שורת־קוד־אחת, כך שסעיף זה תמציתי - אך Perl כן, וברגע שאתם משאירים את Tcl מאחור כדאי לדעת שהרפלקס קיים. משפחת המתגים: `-e` מספק את התוכנית, `-n` עוטף אותה בלולאה ללא הדפסה אוטומטית, `-p` עוטף אותה בלולאת הדפסה אוטומטית, `-i` עורך במקום, ו־`-a`/`-F` מפצלים אוטומטית כל שורה אל `@F`. בלוקי `BEGIN { }` ו־`END { }` רצים לפני ואחרי הלולאה. ```perl perl -ne 'print if /error/' log.txt # print matching lines perl -pe 's/\d+/N/g' input.txt # mask numbers perl -nE 'END { say $n } $n++ if /error/' log.txt # count, END block ``` אלה מוצגים ללא פלט מכיוון שמתגי הלולאה המשתמעת אינם מזוהים על ידי build זה של `pperl` עדיין (ראו את ההערה בראש). כל אחד ממופה לצורת לולאה מפורשת מאומתת: `perl -ne 'CODE'` הוא `while (<$fh>) { CODE }`, ו־`perl -pe 'CODE'` הוא אותו דבר עם `print` נגרר. הצורה הניתנת־להרצה ”ספירת שורות תואמות“: ```perl use v5.42; open my $fh, '<', '/tmp/tcl_data.txt' or die "open: $!"; my $n = 0; while (<$fh>) { $n++ if /banana/; # the body of -ne } say $n; # 1 ``` המלכודת: עד שהמתגים ייכנסו ל־`pperl`, כתבו את הלולאה המפורשת (היא רצה היום וזה ממילא מה שהמתגים מתרחבים אליו), ועיינו ב[מדריך שורות־הקוד־האחת](../oneliner/index.md) לקטלוג המתגים המלא ולמתכונים. ל־Perl יש גם תת־שגרות מלאות, הפניות, מודולים, ותכנות מונחה־עצמים אם הסקריפט שלכם גדל מעבר למשימת דבק: המחלקות `namespace eval` ו־`[incr Tcl]` של Tcl ממופות לחבילות Perl ולתחביר ה־`class` המודרני; ראו את [מדריך התכנות מונחה־העצמים](../oop/index.md) לצד הזה של השפה. ## מלכודות בהגעה מ־Tcl המלכודות, מקובצות לסריקה אחרונה לפני שאתם כותבים: - **שתי משפחות השוואה.** `==`/`<`/`<=>` משווים מספרית; `eq`/`lt`/`cmp` משווים כמחרוזות. `"10" == "10.0"` הוא אמת, `"10" eq "10.0"` הוא שקר. בחרו לפי הפעולה, לא לפי הערך - הבאג השקט האחד שהשקפת־העולם של מחרוזת־תחילה מזמינה. - **הסיגיל עוקב אחר האיבר.** איבר אחד של `@items` הוא `$items[0]` (סקלר), לא `@items[0]`; ערך אחד של `%a` הוא `$a{red}`. סיגיל המכל וסיגיל האיבר שונים. - **`sort` ממוין כמחרוזות כברירת מחדל,** כמו השוואה עם `eq`. העבירו `{ $a <=> $b }` לסדר מספרי. - **`s///` מחזיר ספירה, לא את המחרוזת החדשה,** ועורך במקום. העתיקו תחילה (`(my $t = $s) =~ s/.../.../`) או השתמשו בדגל `/r` למחרוזת רעננה. - **`tr///` (המקבילה ל־`string map`) הוא קבוצת תווים מילולית, לא ביטוי רגולרי.** `tr/ab/AB/` ממפה תווים בודדים. לתבניות, השתמשו ב־`s///`. - **`split ' '` ו־`split / /` שונים.** מחרוזת הרווח־המילולי מפצלת על רצפי רווחים לבנים ומשמיטה ריקים מובילים (מחלק־המילים־לאסימונים); ביטוי הרווח־האחד אינו עושה זאת. השתמשו ב־`split ' '` לקלט חופשי־צורה. - **`<$fh>` שומר על תו השורה החדשה הנגרר,** בניגוד ל־`gets` של Tcl. קראו ל־`chomp` כדי לקצץ אותו. - **`open` אינו זורק חריגה בכישלון.** השתמשו ב־`open my $fh, '<', $path or die "...: $!"`. `$!` היא מחרוזת שגיאת המערכת; אין `catch` לעטוף אותה. - **הפניות מחליפות את `upvar`.** כדי לשנות משתנה של הקורא, העבירו הפניה (`\$x`, `\@arr`, `\%h`) במכוון במקום לכנות לפי שם. הפניות הן גם הדרך שבה Perl מקננת נתונים. - **בלוק `{ ... }` הוא קוד, לא מחרוזת נדחית.** Perl מנתחת בלוקים בזמן ההידור; אין שלב של ”הגוף הוא מחרוזת עד שאני מריץ אותו“. רק `''`/`""` נושאים את הבחנת ההחלפה `{}`/`""` של Tcl. - **מתגי הלולאה המשתמעת (`-n`/`-p`/`-a`/`-F`/`-i`/`-l`) עדיין אינם מזוהים על ידי build זה של `pperl`.** רק `-e` עובד היום. כתבו את הלולאה המפורשת `while (<$fh>) { ... }`, שהיא בדיוק מה שהמתגים מתרחבים אליו, עד שהם ייכנסו.