Random Thoughts

Thursday, April 17, 2008

Perl Tutorial: Don't name a variable i, y or j

I worked with a guy named Dean back in 89-91 at Dupont that taught me a really simple trick. Most people use the variable names i, y or j for simple counters ( damn Fortran). I don't know about emacs, but in vi, a search for 'i' is painful. But searching for "ii" is much less painful.

My counters are now always 2 letters for this reason.

So if you are going to use simple non-descriptive pointer variables, use something you can reasonably search.

Labels: , ,

Sunday, April 13, 2008

Perl tutorial : usage() and here dcuments

I tend to write many Perl utilities. Some are just a few hundred lines. But the user needs to know how to use it. As is usual, written documentation is not well maintained and rarely read. But if the default behavior of a application is to print a small man page when there is an invalid parameter, then you have useful and used documentation.

I make this a feature of everything I expect to be used by others. If it is that complex, I put it in anyway so I do not have to read the code. Just run
myscript -help
Actually any invalid option will work. I usually don't have a specific test for "-help".

Here documents like in shell scripts are handled like double quoted strings. Variables are interpreted.

So instead of
sub usage
{
print "fobar() -dir DIR\n";
print " -dir DIR is the directory to ...\n";
exit(); //yes I always assume that usage() is an exit point.
}

do
sub usage
{
print <<endodcs
fobar() -dir DIR
-dir DIR is the directory to ...
enddocs
; #end of print statement
exit();
}


Labels: , , ,

Thursday, April 10, 2008

Perl Tutorial: Function Pointers

In C the function pointer is how to passing functions around. In Perl using an ampersand in front of a string is treated an a function call.

sub foo { print "called foo\n"; }
our $functname = "foo";
&{$funcname}();

Using this technique, I was able to override functions based on the product I was building.

For the current default product I has a series of calls to perform a build. Some might be:
  • checkout
  • email
  • installer
So I set a naming convention. Another product lets say foobar1_0 was a previous build and the current product is foobar2_0. The checkout or installer procedure might have changed between the two releases.

The current script will build foobar2_0 by default. But when foobar1_0 requires a patch release, a build has to be done using the old checkout and installer procedures.

I define a library foobar1_0.pm for the foobar1_0 build rules:

sub foobar1_0_checkout()
{
}
sub foobar1_0_installer()
{
}

//we are defining overrides for checkout and installer,
// but like build, nothing else is overridden. e.x in the full code, there are
// about 40 definitions of function and global variables.
//NOP is a No op function for functions that are not to be run.
%foobar1_0_map = {
# variables that need to be set
"checkout"=> "foobar1_0_checkout",
"installer"=> "foobar1_0_installer",
"make_test" => "NOP"
"build"=>"build"
};
In the main build script we do the following:

//$project_prefix is a parameter. in our case "foobar1_0"
$curmapname = $project_prefix."_map"

//Notice %$curmapname is also a indirect reference.
//%cur_map is now a reference to %foobar1_0_map
%cur_map = %$curmapname
If the main project is built, we do not override %cur_map. But no matter what, we do a checkout by calling
&{$cur_map{checkout}}();

The truth is, I even allow main to be overridden. Yes, in my perl code I usually define a main() function.

So, function pointers are alive an well in Perl.

Note: You can not use strict to do this coding. If someone finds a way, I'd love to update this posting.

Labels: , ,

Wednesday, April 09, 2008

Perl Tutorials

I've been doing some heavy Perl coding for over 5 years now. I think my most challenging was a build script I inherited. When I started, there was one copy of the script for each branch and there was no error checking.

This means bugs in one had to be fixed in 2-3 other places. Also the build rarely ran to successful completion.

When I left 3 years later, there was one script. Not only was there only one script, but it handled multiple products.

I am going to write series of post detailing the tricks. Many have been published elsewhere. One or two of them I have only seen in this particular piece of code.

I'll try to write 1 or 2 posts a week until I exhaust this topic.

Labels: ,


-->