Most of what follows in this appendix is taken directly from the PERLTRAP manual section, which the author maintains. It's included here for your convenience in making the transition from Perl4 to Perl5. The latest revision of this document is always available within the Perl distribution.
Practicing Perl4 programmers should take note of the following Perl4 to Perl5
conversion-
specific traps.
They're generally ordered according to the following list: Discontinuance, Deprecation,
Anything that's been fixed as a Perl4 bug,
and BugFix traps removed as a Perl4 feature, or deprecated as a Perl4 feature with
the intent to encourage usage of
some other Perl5 feature.
Parsing traps Traps that appear to stem from the new parser.
Numerical traps Traps having to do with numerical or mathematical operators.
General data type traps Traps involving Perl standard data types.
Context traps--scalar, Traps related to context within lists and scalar
list contexts statements/declarations.
Precedence Traps Traps related to the precedence of parsing, evaluation, and execution of code.
General Regular Expression Traps related to the use of pattern matching.
traps using s///, and so on
Subroutine, Signal, Traps related to the use of signals and signal
Sorting traps handlers, general subroutines, and sorting,
along with sorting subroutines.
OS traps OS-specific traps.
DBM traps Traps specific to the use of dbmopen() and specific dbm implementations.
Unclassified traps Everything else.
If you find an example of a conversion trap that is not listed here, please submit it to the Perl5 Porters <perl5-porters@nicoh.com> for inclusion. Also note that at least some of these can be caught with the command-line option, -w.
Anything that has been discontinued, deprecated, or fixed as a bug from Perl4.
package test;
$_legacy = 1;
package main;
print "\$_legacy is ",$_legacy,"\n";
# perl4 prints: $_legacy is 1
# perl5 prints: $_legacy is
goto marker1;
for(1){
marker1:
print "Here I is!\n";
}
# perl4 prints: Here I is!
# perl5 dumps core (SEGV)
$a = ("foo bar");
$b = q baz ;
print "a is $a, b is $b\n";
# perl4 prints: a is foo bar, b is baz
# perl5 errors: Bare word found where operator expected
if { 1 } {
print "True!";
}
else {
print "False!";
}
# perl4 prints: True!
# perl5 errors: syntax error at test.pl line 1, near "if {"
@list = (`ab','abc','bcd','def');
foreach $var (grep(/ab/,@list)){
$var = 1;
}
print (join(`:',@list));
# perl4 prints: ab:abc:bcd:def
# perl5 prints: 1:1:bcd:def
foreach $var (grep(/ab/,@list)){
foreach $var (@tmp = grep(/ab/,@list)){
$_ = ' hi mom';
print join(`:', split);
# perl4 prints: :hi:mom
# perl5 prints: hi:mom
$a=1;$b=2;$c=3;$var=4;
print "$a::$b::$c ";
print "$var::abc::xyz\n";
# perl4 prints: 1::2::3 4::abc::xyz
# perl5 prints: 3
$x = 10 ;
print "x=${`x}\n" ;
# perl4 prints: x=10
# perl5 prints: Can't find string terminator "'" anywhere before EOF
sub sub1{return(0,2) } # return a 2-elem array
sub sub2{ return(1,2,3)} # return a 3-elem array
@a1 = ("a","b","c","d","e");
@a2 = splice(@a1,&sub1,&sub2);
print join(` ',@a2),"\n";
# perl4 prints: a b
# perl5 prints: c d e
print -4**2,"\n";
# perl4 prints: 16
# perl5 prints: -16
Perl4 to Perl5 traps having to do with parsing.
$string . = "more string";
print $string;
# perl4 prints: more string
# perl5 prints: syntax error at - line 1, near ". ="
sub foo {}
&foo
print("hello, world\n");
# perl4 prints: hello, world
# perl5 prints: syntax error
($foo == 1) ? "is one\n" : "is zero\n";
# perl4 prints: is zero
# perl5 warns: "Useless use of a constant in void context" if using -w
Perl4 to Perl5 traps having to do with numerical operators, operands, or output from same.
print 7.373504 - 0, "\n";
printf "%20.18f\n", 7.373504 - 0;
# Perl4 prints:
7.375039999999996141
7.37503999999999614
# Perl5 prints:
7.373504
7.37503999999999614
$p = ($test == 1); print $p,"\n";
# perl4 prints: 0
# perl5 prints:
Perl4 to Perl5 traps involving most data types and their usage within certain expressions and/or context.
@a = (1, 2, 3, 4, 5);
print "The third element of the array is $a[3] also expressed as $a[-2] \n";
# perl4 prints: The third element of the array is 4 also expressed as
# perl5 prints: The third element of the array is 4 also expressed as 4
@a = (a,b,c,d,e);
print "Before: ",join(``,@a);
$#a =1;
print ", After: ",join(``,@a);
$#a =3;
print ", Recovered: ",join(``,@a),"\n";
# perl4 prints: Before: abcde, After: ab, Recovered: abcd
# perl5 prints: Before: abcde, After: ab, Recovered: ab
local($s,@a,%h);
die "scalar \$s defined" if defined($s);
die "array \@a defined" if defined(@a);
die "hash \%h defined" if defined(%h);
# perl4 prints:
# perl5 dies: hash %h defined
@a = ("This is Perl 4");
*b = *a;
local(@a);
print @b,"\n";
# perl4 prints: This is Perl 4
# perl5 prints:
# Another example
*fred = *barney; # fred is aliased to barney
@barney = (1, 2, 4);
# @fred;
print "@fred"; # should print "1, 2, 4"
# perl4 prints: 1 2 4
# perl5 prints: Literal @fred now requires backslash
$x = "aaa";
print ++$x," : ";
print -$x," : ";
print ++$x,"\n";
# perl4 prints: aab : -0 : 1
# perl5 prints: aab : -aab : aac
$foo = "x";
&mod($foo);
for ($x = 0; $x < 3; $x++) {
&mod("a");
}
sub mod {
print "before: $_[0]";
$_[0] = "m";
print " after: $_[0]\n";
}
# perl4:
# before: x after: m
# before: a after: m
# before: m after: m
# before: m after: m
# Perl5:
# before: x after: m
# Modification of a read-only value attempted at foo.pl line 12.
# before: a
print "$x", defined $x
# perl 4: 1
# perl 5: <no output, $x is not called into existence>
$aGlobal{ "aKey" } = "global value";
print "MAIN:", $aGlobal{"aKey"}, "\n";
$GlobalLevel = 0;
&test( *aGlobal );
sub test {
local( *theArgument ) = @_;
local( %aNewLocal ); # perl 4 != 5.001l,m
$aNewLocal{"aKey"} = "this should never appear";
print "SUB: ", $theArgument{"aKey"}, "\n";
$aNewLocal{"aKey"} = "level $GlobalLevel"; # what should print
$GlobalLevel++;
if( $GlobalLevel<4 ) {
&test( *aNewLocal );
}
}
# Perl4:
# MAIN:global value
# SUB: global value
# SUB: level 0
# SUB: level 1
# SUB: level 2
# Perl5:
# MAIN:global value
# SUB: global value
# SUB: this should never appear
# SUB: this should never appear
# SUB: this should never appear
Traps that involve scalar versus list contexts.
@fmt = ("foo","bar","baz");
format STDOUT=
@<<<<< @||||| @>>>>>
@fmt;
.
write;
# perl4 errors: "Please use commas to separate fields in file" if using -w
# perl5 prints: foo bar baz
caller() ? (print "You rang?\n") : (print "Got a 0\n");
# perl4 errors: There is no caller
# perl5 prints: Got a 0
@y= (`a','b','c');
$x = (1, 2, @y);
print "x = $x\n";
# Perl4 prints: x = c # Thinks list context interpolates list
# Perl5 prints: x = 3 # Knows scalar uses length of list
@z = (`%s%s', 'foo', 'bar');
$x = sprintf(@z);
if ($x eq 'foobar') {print "ok 2\n";} else {print "not ok 2 '$x'\n";}
# perl4 prints: ok 2
# perl5 prints: not ok 2
printf() works fine, though:
printf STDOUT (@z);
print "\n";
# perl4 prints: foobar
# perl5 prints: foobar
Perl4 to Perl5 traps involving precedence of operations and ordering.
@arr = ( 'left', 'right' );
$a{shift @arr} = shift @arr;
print join( ' ', keys %a );
# perl4 prints: left
# perl5 prints: right
@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";
# perl4 prints: n is 3, m is 6
# perl5 errors and fails to compile
/foo/ ? ($a += 2) : ($a -= 2);
/foo/ ? $a += 2 : $a -= 2
(/foo/ ? $a += 2 : $a) -= 2;
$a += /foo/ ? 1 : 2;
open FOO || die;
open(FOO || die);
# perl4 opens or dies
# perl5 errors: Precedence problem: open FOO should be open(FOO)
$a = "x"; print "$::a";
# perl 4 prints: -:a
# perl 5 prints: x
-e $foo .= "q"
# perl4 prints: no output
# perl5 prints: Can't modify -e in concatenation
@arr = ( 'left', 'right' );
$a{shift @arr} = shift @arr;
print join( ' ', keys %a );
# perl4 prints: left
# perl5 prints: right
All types of regular expression and regular expression operator traps.
$a=1;$b=2;
$string = '1 2 $a $b';
$string =~ s'$a'$b';
print $string,"\n";
# perl4 prints: $b 2 $a $b
# perl5 prints: 1 2 $a $b
$_ = "ababab";
while(m/ab/g){
&doit("blah");
}
sub doit{local($_) = shift; print "Got $_ "}
# perl4 prints: blah blah blah
# perl5 prints: infinite loop blah...
$string = "test";
$value = ($string =~ s/foo//);
print $value, "\n";
# perl4 prints: 0
# perl5 prints:
$string = "";
$string =~ s'^'hostname';
print $string, "\n";
# perl4 prints: <the local hostname>
# perl5 prints: hostname
s/^([^$grpc]*$grpc[$opt$plus$rep]?)//o;
# perl4: compiles w/o error
# perl5: with Scalar found where operator expected ..., near "$opt$plus"
$grpc = 'a';
$opt = 'r';
$_ = 'bar';
s/^([^$grpc]*$grpc[$opt]?)/foo/;
print ;
# perl4 prints: foo
# perl5 prints: foobar
$test = "once";
sub match { $test =~ m?once?; }
&match();
if( &match() ) {
# m?x? matches more then once
print "perl4\n";
} else {
# m?x? matches only once
print "perl5\n";
}
# perl4 prints: perl4
# perl5 prints: perl5
The general group of Perl4 to Perl5 traps having to do with signals, sorting, and their related subroutines, as well as general subroutine traps. Includes some OS-specific traps.
sub SeeYa { warn"Hasta la vista, baby!" }
$SIG{`TERM'} = SeeYa;
print "SIGTERM is now $SIG{`TERM'}\n";
# perl4 prints: SIGTERM is main'SeeYa
# perl5 prints: SIGTERM is now main::1
sub reverse{ print "yup "; $a <=> $b }
print sort reverse a,b,c;
# perl4 prints: yup yup yup yup abc
# perl5 prints: abc
warn STDERR "Foo!";
# perl4 prints: Foo!
# perl5 prints: String found where operator expected
sub gotit {
print "Got @_... ";
}
$SIG{`INT'} = 'gotit';
$| = 1;
$pid = fork;
if ($pid) {
kill(`INT', $pid);
sleep(1);
kill(`INT', $pid);
} else {
while (1) {sleep(10);}
}
# perl4 (HPUX) prints: Got INT...
# perl5 (HPUX) prints: Got INT... Got INT...
Perl4 to Perl5 traps having to do with how things get interpolated within certain expressions, statements, contexts, or whatever.
print "To: someone@somewhere.com\n";
# perl4 prints: To:someone@somewhere.com
# perl5 errors : Literal @somewhere now requires backslash
$foo = "foo$";
$bar = "bar@";
print "foo is $foo, bar is $bar\n";
# perl4 prints: foo is foo$, bar is bar@
# perl5 errors: Final $ should be \$ or $name
@www = "buz";
$foo = "foo";
$bar = "bar";
sub foo { return "bar" };
print "|@{w.w.w}|${main'foo}|";
# perl4 prints: |@{w.w.w}|foo|
# perl5 prints: |buz|bar|
print "this is $$x\n";
# perl4 prints: this is XXXx (XXX is the current pid)
# perl5 prints: this is
$hashname = "foobar";
$key = "baz";
$value = 1234;
eval "\$$hashname{`$key'} = q|$value|";
(defined($foobar{`baz'})) ? (print "Yup") : (print "Nope");
# perl4 prints: Yup
# perl5 prints: Nope
Changing
eval "\$$hashname{`$key'} = q|$value|";
to
eval "\$\$hashname{`$key'} = q|$value|";
causes the following result:
# perl4 prints: Nope
# perl5 prints: Yup
or, changing to
eval "\$$hashname\{`$key'\} = q|$value|";
causes the following result:
# perl4 prints: Yup
# perl5 prints: Yup
# and is compatible for both versions
perl -e '$bar=q/not/; print "This is $foo{$bar} perl5"'
# perl4 prints: This is not perl5
# perl5 prints: This is perl5
print "$foo{"
perl 4 prints: {
perl 5 prints: syntax error
$foo = "array";
print "\$$foo{bar}\n";
# perl4 prints: $array{bar}
# perl5 prints: $
eval qq(
foreach \$y (keys %\$x\) {
\$count++;
}
);
# perl4 runs this ok
# perl5 prints: Can't find string terminator ")"
General DBM traps.
dbmopen (%dbm, "file", undef);
print "ok\n";
# perl4 prints: ok
# perl5 prints: ok (IFF linked with -ldbm or -lndbm)
dbmopen(DB, "testdb",0600) || die "couldn't open db! $!";
$DB{`trap'} = "x" x 1024; # value too large for most dbm/ndbm
print "YUP\n";
# perl4 prints:
dbm store returned -1, errno 28, key "trap" at - line 3.
YUP
# perl5 prints:
dbm store returned -1, errno 28, key "trap" at - line 3.
Everything else.
sub foo {
$rc = do "./do.pl";
return 8;
}
print &foo, "\n";
return 3;
# perl 4 prints: 3 (aborts the subroutine early)
# perl 5 prints: 8