|
|
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);