|
|
|
PGTS High and Mighty BlogThread: Perl Programming |
|
|
Gerry Patterson. The world's most humble blogger |
| Edited and endorsed by PGTS, Home of the world's most humble blogger | |
| | |
Those Bold No Strict Days |
|
Chronogical Blog Entries:
|
|
| | |
Date: Thu, 29 May 2008 00:56:48 +1000When I first started using perl (about ten years ago), I was a bold and irreverent awk convert (i.e. converted from C). In my first trial of perl I just ploughed into programming without using the strict or warnings pragmas. I was a programmer on the edge, having thrown off the tight boots of C declarations, reveling in my awk freedom. |
|
Of course as some of those perl programs grew, I became more enthusiastic about these two pragmas.
However one of the annoying things that I found was incrementing simple counters. In my earlier bold no strict, no warnings days I could do something like:
if ( $foo{$bar}++ <= $#baz) {
blah blah blah
....
}
And the hash element (and the variable $bar) would be defined "on the fly" and would furthermore be post-incremented every time the test was executed.
In the rather less bold, and more sensible strict environment, I would have to say:
$foo{bar} = 0 unless ($foo{bar});
if ( $foo{$bar}++ <= $#baz) {
blah blah blah
....
}
Of course I would also need these declarations somewhere in the strict code:
my $bar; my %foo; my @baz;
Ok, it's only an extra statement, but in a very large script I might do it hundreds of times. It gets rather tedious.
One way around this might be to say:
if ( ($foo{$bar} = ($foo{$bar} ) ? ++$foo{$bar} : 1) < $#baz) {
blah blah blah
....
}
That would get the job done with a single statement. And it might also win you a minor mention in the obfuscation dispatches. Note: this now acts like a pre-increment operator, so in order to make the code equivalent the comparison uses < rather than <=.
With the following subroutine:
use subs qw(incr);
sub incr {
return (++$_[0]) if ($_[0]);
return 1;
}
It might be possible to use the incr() subroutine in place of a pre-increment operator. But wherever it is invoked it would have to be as follows:
$foo = incr($foo);
Note: Because it has been declared with the subs pragma, you can omit the brackets:
$foo = incr $foo ;
The following code, may be a bit long-winded. But in a large script, it might be useful:
use subs qw(pre_mod post_incr);
sub pre_mod {
my ($scalaref,$incr) = @_;
$incr = 1 unless ($incr);
if ($$scalaref) {
$$scalaref += $incr;
} else {
$$scalaref = $incr;
}
return($$scalaref);
}
sub post_mod {
my ($scalaref,$incr) = @_;
my $v = ($$scalaref) ? $$scalaref : 0;
$incr = 1 unless ($incr);
if ($$scalaref) {
$$scalaref += $incr;
} else {
$$scalaref = $incr;
}
return($v);
}
This would mean that the following code could be used:
if ( post_mod(\$foo{$bar}) <= $#baz) {
blah blah blah
....
}
or
if ( pre_mod(\$foo{$bar}) < $#baz) {
blah blah blah
....
}
And if you want to post-increment by a value other than 1 you can say;
my $foo = post_mod(\$blah,5); my $bar = post_mod(\$ecky,-1);
PGTS Pty. Ltd.   ACN: 007 008 568