I am looking for bugs that you might not make any more but either you used to make or you know others often make it. Little annoyances that can easily trip the unaware without perl warning them.
While reading the Minimal Perl by Tim Maher I encountered two warnings about mistakes beginners might make. Based on those two I started to collect some little mistakes people can make in Perl but that perl does not catch.
The first two are based on the warnings from Minimal Perl:
chomp does not return the string
The correct way of course would be to just write:print "type in something: "; my $line = <STDIN>; $line = chomp $line;
print "type in something: "; my $line = <STDIN>; chomp $line;
substitute returns true/false and not the changed string even in map
The above prints 1 1 1my @data = qw(foo bar baz); @data = map { s/./X/ } @data; print "@data\n";
The correct way would be to let map return the changed value instead of the success/failure code of the substitution.
my @data = qw(foo bar baz); @data = map { s/./X/; $_} @data; print "@data\n";
|| has higher precedence than ,
|| being higher precedence that above is the same asmy $filename = 'input.txt'; open my $fh, '<', $filename || die $!;
which means first the || is evaluated which will always be true (except of the stupid edge cases such as $filename being empty string or 0) so in normal circumstances everything will work but if the open fails, it still won't be reported.open my $fh, '<', ($filename || die $!);
The correct would be to either use or instead of || or put parentheses around the parameters of open(). Personally I try to write and teach this form:
my $filename = 'input.txt'; open(my $fh, '<', $filename) or die $!;
Perl 6-like constructs work in perl 5
A student of mine had to iterate over the values of an array so he wrote:The annoying part here is that this works despite being incorrect.my @names = qw(A B C); foreach my $name (<@names>) { print "$name\n"; }
We are talking about Perl 5 here!.
Using perl -MO=Deparse example.pl reveals what perl thought about the above code:
my(@names) = ('A', 'B', 'C'); use File::Glob (); foreach my $name (glob(join($", @names))) { print "$name\n"; }
magic $_ regex matching
That will try to match $_ with /x/my $x = 42; if ($x = /x/) { print "ok\n"; }
If you are lucky you get Use of uninitialized value $_ in pattern match (m//) at code.pl line 32.. If you are unlucky and $_ already had a value the above will make the mistake silently.
I am not saying it is not legitimate code. I am saying I see beginners write that by mistake without understanding what that means.
or is weaker than return
Based on the example given by rhesaThe above will return 0 despite it being false and will do it silently.my $x = 42; print is_foo_or(); sub is_foo_or { return foo($x) or $x; } sub foo { return 0; }