<P>The biggest trap of all is forgetting to use the <STRONG>-w</STRONG> switch; see
<A HREF="../../lib/Pod/perlrun.html">the perlrun manpage</A>. The second biggest trap is not making your entire program
runnable under <CODE>use strict</CODE>. The third biggest trap is not reading
the list of changes in this version of Perl; see <A HREF="../../lib/Pod/perldelta.html">the perldelta manpage</A>.</P>
<P>
<H2><A NAME="awk traps">Awk Traps</A></H2>
<P>Accustomed <STRONG>awk</STRONG> users should take special note of the following:</P>
<UL>
<LI>
The English module, loaded via
<PRE>
use English;</PRE>
<P>allows you to refer to special variables (like <CODE>$/</CODE>) with names (like
$RS), as though they were in <STRONG>awk</STRONG>; see <A HREF="../../lib/Pod/perlvar.html">the perlvar manpage</A> for details.</P>
<P></P>
<LI>
Semicolons are required after all simple statements in Perl (except
at the end of a block). Newline is not a statement delimiter.
<P></P>
<LI>
Curly brackets are required on <CODE>if</CODE>s and <CODE>while</CODE>s.
<P></P>
<LI>
Variables begin with ``$'', ``@'' or ``%'' in Perl.
<P></P>
<LI>
Arrays index from 0. Likewise string positions in <A HREF="../../lib/Pod/perlfunc.html#item_substr"><CODE>substr()</CODE></A> and
index().
<P></P>
<LI>
You have to decide whether your array has numeric or string indices.
<P></P>
<LI>
Hash values do not spring into existence upon mere reference.
<P></P>
<LI>
You have to decide whether you want to use string or numeric
comparisons.
<P></P>
<LI>
Reading an input line does not split it for you. You get to split it
to an array yourself. And the <A HREF="../../lib/Pod/perlfunc.html#item_split"><CODE>split()</CODE></A> operator has different
arguments than <STRONG>awk</STRONG>'s.
<P></P>
<LI>
The current input line is normally in $_, not $0. It generally does
not have the newline stripped. ($0 is the name of the program
executed.) See <A HREF="../../lib/Pod/perlvar.html">the perlvar manpage</A>.
<P></P>
<LI>
$<<EM>digit</EM>> does not refer to fields--it refers to substrings matched
by the last match pattern.
<P></P>
<LI>
The <A HREF="../../lib/Pod/perlfunc.html#item_print"><CODE>print()</CODE></A> statement does not add field and record separators unless
you set <CODE>$,</CODE> and <CODE>$\</CODE>. You can set $OFS and $ORS if you're using
the English module.
<P></P>
<LI>
You must open your files before you print to them.
<P></P>
<LI>
The range operator is ``..'', not comma. The comma operator works as in
C.
<P></P>
<LI>
The match operator is ``=~'', not ``~''. (``~'' is the one's complement
operator, as in C.)
<P></P>
<LI>
The exponentiation operator is ``**'', not ``^''. ``^'' is the XOR
operator, as in C. (You know, one could get the feeling that <STRONG>awk</STRONG> is
basically incompatible with C.)
<P></P>
<LI>
The concatenation operator is ``.'', not the null string. (Using the
null string would render <CODE>/pat/ /pat/</CODE> unparsable, because the third slash
would be interpreted as a division operator--the tokenizer is in fact
slightly context sensitive for operators like ``/'', ``?'', and ``>''.
And in fact, ``.'' itself can be the beginning of a number.)
<P></P>
<LI>
The <A HREF="../../lib/Pod/perlfunc.html#item_next"><CODE>next</CODE></A>, <A HREF="../../lib/Pod/perlfunc.html#item_exit"><CODE>exit</CODE></A>, and <A HREF="../../lib/Pod/perlfunc.html#item_continue"><CODE>continue</CODE></A> keywords work differently.
<P></P>
<LI>
The following variables work differently:
<PRE>
Awk Perl
ARGC $#ARGV or scalar @ARGV
ARGV[0] $0
FILENAME $ARGV
FNR $. - something
FS (whatever you like)
NF $#Fld, or some such
NR $.
OFMT $#
OFS $,
ORS $\
RLENGTH length($&)
RS $/
RSTART length($`)
SUBSEP $;</PRE>
<P></P>
<LI>
You cannot set $RS to a pattern, only a string.
<P></P>
<LI>
When in doubt, run the <STRONG>awk</STRONG> construct through <STRONG>a2p</STRONG> and see what it
gives you.
<P></P></UL>
<P>
<H2><A NAME="c traps">C Traps</A></H2>
<P>Cerebral C programmers should take note of the following:</P>
<UL>
<LI>
Curly brackets are required on <CODE>if</CODE>'s and <CODE>while</CODE>'s.
<P></P>
<LI>
You must use <CODE>elsif</CODE> rather than <CODE>else if</CODE>.
<P></P>
<LI>
The <CODE>break</CODE> and <A HREF="../../lib/Pod/perlfunc.html#item_continue"><CODE>continue</CODE></A> keywords from C become in
Perl <A HREF="../../lib/Pod/perlfunc.html#item_last"><CODE>last</CODE></A> and <A HREF="../../lib/Pod/perlfunc.html#item_next"><CODE>next</CODE></A>, respectively.
Unlike in C, these do <EM>not</EM> work within a <CODE>do { } while</CODE> construct.
<P></P>
<LI>
There's no switch statement. (But it's easy to build one on the fly.)
<P></P>
<LI>
Variables begin with ``$'', ``@'' or ``%'' in Perl.
<P></P>
<LI>
<A HREF="../../lib/Pod/perlfunc.html#item_printf"><CODE>printf()</CODE></A> does not implement the ``*'' format for interpolating
field widths, but it's trivial to use interpolation of double-quoted
strings to achieve the same effect.
<P></P>
<LI>
Comments begin with ``#'', not ``/*''.
<P></P>
<LI>
You can't take the address of anything, although a similar operator
in Perl is the backslash, which creates a reference.
<P></P>
<LI>
<CODE>ARGV</CODE> must be capitalized. <CODE>$ARGV[0]</CODE> is C's <CODE>argv[1]</CODE>, and <CODE>argv[0]</CODE>
ends up in <CODE>$0</CODE>.
<P></P>
<LI>
System calls such as link(), unlink(), rename(), etc. return nonzero for
success, not 0.
<P></P>
<LI>
Signal handlers deal with signal names, not numbers. Use <CODE>kill -l</CODE>
to find their names on your system.
<P></P></UL>
<P>
<H2><A NAME="sed traps">Sed Traps</A></H2>
<P>Seasoned <STRONG>sed</STRONG> programmers should take note of the following:</P>
<UL>
<LI>
Backreferences in substitutions use ``$'' rather than ``\''.
<P></P>
<LI>
The pattern matching metacharacters ``('', ``)'', and ``|'' do not have backslashes
in front.
<P></P>
<LI>
The range operator is <CODE>...</CODE>, rather than comma.
<P></P></UL>
<P>
<H2><A NAME="shell traps">Shell Traps</A></H2>
<P>Sharp shell programmers should take note of the following:</P>
<UL>
<LI>
The backtick operator does variable interpolation without regard to
the presence of single quotes in the command.
<P></P>
<LI>
The backtick operator does no translation of the return value, unlike <STRONG>csh</STRONG>.
<P></P>
<LI>
Shells (especially <STRONG>csh</STRONG>) do several levels of substitution on each
command line. Perl does substitution in only certain constructs
such as double quotes, backticks, angle brackets, and search patterns.
<P></P>
<LI>
Shells interpret scripts a little bit at a time. Perl compiles the
entire program before executing it (except for <CODE>BEGIN</CODE> blocks, which
execute at compile time).
<P></P>
<LI>
The arguments are available via @ARGV, not $1, $2, etc.
<P></P>
<LI>
The environment is not automatically made available as separate scalar
variables.
<P></P></UL>
<P>
<H2><A NAME="perl traps">Perl Traps</A></H2>
<P>Practicing Perl Programmers should take note of the following:</P>
<UL>
<LI>
Remember that many operations behave differently in a list
context than they do in a scalar one. See <A HREF="../../lib/Pod/perldata.html">the perldata manpage</A> for details.
<P></P>
<LI>
Avoid barewords if you can, especially all lowercase ones.
You can't tell by just looking at it whether a bareword is
a function or a string. By using quotes on strings and
parentheses on function calls, you won't ever get them confused.
<P></P>
<LI>
You cannot discern from mere inspection which builtins
are unary operators (like <A HREF="../../lib/Pod/perlfunc.html#item_chop"><CODE>chop()</CODE></A> and <A HREF="../../lib/Pod/perlfunc.html#item_chdir"><CODE>chdir())</CODE></A>
and which are list operators (like <A HREF="../../lib/Pod/perlfunc.html#item_print"><CODE>print()</CODE></A> and unlink()).
(User-defined subroutines can be <STRONG>only</STRONG> list operators, never
unary ones.) See <A HREF="../../lib/Pod/perlop.html">the perlop manpage</A>.
<P></P>
<LI>
People have a hard time remembering that some functions
default to $_, or @ARGV, or whatever, but that others which
you might expect to do not.
<P></P>
<LI>
The <FH> construct is not the name of the filehandle, it is a readline
operation on that handle. The data read is assigned to $_ only if the
file read is the sole condition in a while loop:
<PRE>
while (<FH>) { }
while (defined($_ = <FH>)) { }..
<FH>; # data discarded!</PRE>
<P></P>
<LI>
Remember not to use <CODE>=</CODE> when you need <CODE>=~</CODE>;
these two constructs are quite different:
<PRE>
$x = /foo/;
$x =~ /foo/;</PRE>
<P></P>
<LI>
The <A HREF="../../lib/Pod/perlfunc.html#item_do"><CODE>do {}</CODE></A> construct isn't a real loop that you can use
loop control on.
<P></P>
<LI>
Use <A HREF="../../lib/Pod/perlfunc.html#item_my"><CODE>my()</CODE></A> for local variables whenever you can get away with
it (but see <A HREF="../../lib/Pod/perlform.html">the perlform manpage</A> for where you can't).
Using <A HREF="../../lib/Pod/perlfunc.html#item_local"><CODE>local()</CODE></A> actually gives a local value to a global
variable, which leaves you open to unforeseen side-effects
of dynamic scoping.
<P></P>
<LI>
If you localize an exported variable in a module, its exported value will
not change. The local name becomes an alias to a new value but the
external name is still an alias for the original.
<P></P></UL>
<P>
<H2><A NAME="perl4 to perl5 traps">Perl4 to Perl5 Traps</A></H2>
<P>Practicing Perl4 Programmers should take note of the following
Perl4-to-Perl5 specific traps.</P>
<P>They're crudely ordered according to the following list:</P>
<DL>
<DT><STRONG><A NAME="item_Discontinuance%2C_Deprecation%2C_and_BugFix_traps">Discontinuance, Deprecation, and BugFix traps</A></STRONG><BR>
<DD>
Anything that's been fixed as a perl4 bug, removed as a perl4 feature
or deprecated as a perl4 feature with the intent to encourage usage of
LHS vs. RHS of any assignment operator. LHS is evaluated first
in perl4, second in perl5; this can affect the relationship
between side-effects in sub-expressions.
<PRE>
@arr = ( 'left', 'right' );
$a{shift @arr} = shift @arr;
print join( ' ', keys %a );</PRE>
<PRE>
# perl4 prints: left
# perl5 prints: right</PRE>
<P></P>
<LI><STRONG>Precedence</STRONG><BR>
These are now semantic errors because of precedence:
<PRE>
@list = (1,2,3,4,5);
%map = ("a",1,"b",2,"c",3,"d",4);
$n = shift @list + 2; # first item in list plus 2
print "n is $n, ";
$m = keys %map + 2; # number of items in hash plus 2
print "m is $m\n";</PRE>
<PRE>
# perl4 prints: n is 3, m is 6
# perl5 errors and fails to compile</PRE>
<P></P>
<LI><STRONG>Precedence</STRONG><BR>
The precedence of assignment operators is now the same as the precedence
of assignment. Perl 4 mistakenly gave them the precedence of the associated
operator. So you now must parenthesize them in expressions like
<PRE>
/foo/ ? ($a += 2) : ($a -= 2);</PRE>
<P>Otherwise</P>
<PRE>
/foo/ ? $a += 2 : $a -= 2</PRE>
<P>would be erroneously parsed as</P>
<PRE>
(/foo/ ? $a += 2 : $a) -= 2;</PRE>
<P>On the other hand,</P>
<PRE>
$a += /foo/ ? 1 : 2;</PRE>
<P>now works as a C programmer would expect.</P>
<P></P>
<LI><STRONG>Precedence</STRONG><BR>
<PRE>
open FOO || die;</PRE>
<P>is now incorrect. You need parentheses around the filehandle.
Otherwise, perl5 leaves the statement as its default precedence:</P>
<PRE>
open(FOO || die);</PRE>
<PRE>
# perl4 opens or dies
# perl5 errors: Precedence problem: open FOO should be open(FOO)</PRE>
<LI><STRONG>Precedence</STRONG><BR>
perl4 gives the special variable, <CODE>$:</CODE> precedence, where perl5
treats <CODE>$::</CODE> as main <A HREF="../../lib/Pod/perlfunc.html#item_package"><CODE>package</CODE></A>
<PRE>
$a = "x"; print "$::a";</PRE>
<PRE>
# perl 4 prints: -:a
# perl 5 prints: x</PRE>
<P></P>
<LI><STRONG>Precedence</STRONG><BR>
perl4 had buggy precedence for the file test operators vis-a-vis
the assignment operators. Thus, although the precedence table
for perl4 leads one to believe <CODE>-e $foo .= "q"</CODE> should parse as
<CODE>((-e $foo) .= "q")</CODE>, it actually parses as <CODE>(-e ($foo .= "q"))</CODE>.
In perl5, the precedence is as documented.
<PRE>
-e $foo .= "q"</PRE>
<PRE>
# perl4 prints: no output
# perl5 prints: Can't modify -e in concatenation</PRE>
<P></P>
<LI><STRONG>Precedence</STRONG><BR>
In perl4, keys(), <A HREF="../../lib/Pod/perlfunc.html#item_each"><CODE>each()</CODE></A> and <A HREF="../../lib/Pod/perlfunc.html#item_values"><CODE>values()</CODE></A> were special high-precedence operators
that operated on a single hash, but in perl5, they are regular named unary
operators. As documented, named unary operators have lower precedence
than the arithmetic and concatenation operators <CODE>+ - .</CODE>, but the perl4
variants of these operators actually bind tighter than <CODE>+ - .</CODE>.
Thus, for:
<PRE>
%foo = 1..10;
print keys %foo - 1</PRE>
<PRE>
# perl4 prints: 4
# perl5 prints: Type of arg 1 to keys must be hash (not subtraction)</PRE>
<P>The perl4 behavior was probably more useful, if less consistent.</P>
<P></P></UL>
<P>
<H2><A NAME="general regular expression traps using s///, etc.">General Regular Expression Traps using s///, etc.</A></H2>
<LI><STRONG><A NAME="item_require%2Fdo_trap_using_returned_value"><A HREF="../../lib/Pod/perlfunc.html#item_require"><CODE>require</CODE></A>/<A HREF="../../lib/Pod/perlfunc.html#item_do"><CODE>do</CODE></A> trap using returned value</A></STRONG><BR>
If the file doit.pl has:
<PRE>
sub foo {
$rc = do "./do.pl";
return 8;
}
print &foo, "\n";</PRE>
<P>And the do.pl file has the following single line:</P>
<PRE>
return 3;</PRE>
<P>Running doit.pl gives the following:</P>
<PRE>
# perl 4 prints: 3 (aborts the subroutine early)
# perl 5 prints: 8</PRE>
<P>Same behavior if you replace <A HREF="../../lib/Pod/perlfunc.html#item_do"><CODE>do</CODE></A> with <A HREF="../../lib/Pod/perlfunc.html#item_require"><CODE>require</CODE></A>.</P>
<P></P>
<LI><STRONG><A NAME="item_split_on_empty_string_with_LIMIT_specified"><A HREF="../../lib/Pod/perlfunc.html#item_split"><CODE>split</CODE></A> on empty string with LIMIT specified</A></STRONG><BR>
<PRE>
$string = '';
@list = split(/foo/, $string, 2)</PRE>
<P>Perl4 returns a one element list containing the empty string but Perl5
returns an empty list.</P>
</UL>
<P>As always, if any of these are ever officially declared as bugs,