I'm running Perl scripts version 5.28 under Linux Debian with some experimental "extensions" and got an strange behavior. In a mixed Pascal-SQL-Perl programming session, I miss typed a lowercase begin
instead of an else
in an if-else-statement (see test code below) and got an valid but malfunctioning code.
I'm aware that the uppercase BEGIN
keyword belongs to BEGIN, UNITCHECK, CHECK, INIT and END
program "pre- and post-program-running" group. But I used the lowercase begin
variant and I got a valid running code. It seems to me, that the begin {...}
block is executed separately after the if (...) {...}
expression, which causes an unwanted early return.
Has the lowercase begin
any meaning in a Perl case sensitive programming context?
#!/usr/bin/perl
use v5.20;
use strict;
use warnings;
use feature qw(signatures);
no warnings 'once';
no warnings 'experimental';
no warnings 'experimental::signatures';
&if_exotic(1000);
&if_normal(1000);
# --------------------------------------
# Bad variant
# --------------------------------------
sub if_exotic($want) {
if ($want>0) {
print "BAD: ..running $want operations\n";
} begin {
print "BAD: ..nothing to do\n";
return;
}
print "Do something $want times\n";
}
# --------------------------------------
# Good variant
# --------------------------------------
sub if_normal($want) {
if ($want>0) {
print "GOOD: ..running $want operations\n";
} else {
print "GOOD: ..nothing to do\n";
return;
}
print "Do something $want times\n";
}
/usr/bin/perl "test-if-begin"
BAD: ..running 1000 operations
BAD: ..nothing to do
GOOD: ..running 1000 operations
Do something 1000 times
This is Perl's indirect object notation in action.
It allows the (recommended) syntax
PackageName->method(args-list)
to be written as (a "discouraged")
method PackageName arg-list
Let's boil down the example program to
use warnings;
use strict;
indirect_notation_gotcha();
print "all good?\n";
sub indirect_notation_gotcha {
anyword {
print "This body stands for package name\n";
return; # runs before "anyword"
}
}
By the indirect-object syntax the code inside the sub is equivalent to
do {
print "This body stands for package name\n";
return
} -> anyword;
This is legal syntax and at runtime the return
statement is what "saves" it as it never gets to the non-existent anyword
.
If we drop the return
indirect_notation_gotcha();
print "all good?\n";
sub indirect_notation_gotcha {
anyword {
print "This body stands for package name\n";
}
}
Now the anyword
is attempted and we get
This body stands for package name Can't locate object method "anyword" via package "1" (perhaps you forgot to load "1"?) at ...
Directly related
Why is this program valid? I was trying to create a syntax error
Also directly related, more complex and with a twist
In many cases one can see what the interpreter does with the code given to it by using O with Deparse
backend, like
perl -MO=Deparse script.pl
However, with more complex code this may not work, like in the second example above
As shown in the link on top, in newer Perls this is a feature that can be disabled (with v5.32+)
no feature qw(indirect); # v5.32+
In yet newer Perls it gets disabled in the bundle as well
use v5.36;
See perldelta for 5.36.0.