About the usage ‘my $q=new CGI();’

About the usage my $q=new CGI();

  • Why do you switch between OO and function-based use of CGI.pm? Why do you use the, potentially problematic, new CGI syntax instead of the recommended CGI->new syntax?
  • In other languages new is a keyword. In Perl it’s just a method name. Which is what makes new Class rather fragile and best avoided. It’s annoying that there is so much documentation out there that uses this syntax.

Multi-dimensional Array In Perl

Perl don’t have multi-dimensional arrays. Instead what we have is the arrays of array reference of another arrays.
Eg :-

#!/usr/bin/perl
my @a;
$a[0][0]='a';
$a[0][1]='b';
$a[1][0]='c';
$a[1][1]='d';
#so you can call values at array @a as follows
print " Type 1 \n ----------- \n";
print $a[0][0]."\n".$a[0][1]."\n".$a[1][0]."\n".$a[1][1]."\n";
print "\n Type 2 \n ----------- \n";
print $a[0]->[0]."\n".$a[0]->[1]."\n".$a[1]->[0]."\n".$a[1]->[1];

 

Perl – Prohibit Conditional Declarations

Declaring a variable with a post fix conditional is really confusing. If the conditional is false, its not clear if the variable will be false, undefined, undeclared, or what. It’s much more straightforward to make variable declarations separately.

my $foo = $baz if $bar;         #not ok
my $foo = $baz unless $bar              #not ok
our $foo = $baz for @list;              #not ok
local $foo = $baz foreach @list;        #not ok

What’s the difference between iterating over a file with foreach or while in Perl?

What’s the difference between iterating over a file with foreach or while in Perl?

I have a file handle FILE in Perl, and I want to iterate over all the lines in the file. Is there a difference between the following?

while (<FILE>) {
    # do something
}

and

foreach (<FILE>) {
    # do something
}

For most purposes, you probably won’t notice a difference. However, foreach reads each line into a list (not an array) before going through it line by line, whereas while reads one line at a time. As foreach will use more memory and require processing time upfront, it is generally recommended to use while to iterate through lines of a file.

EDIT (via Schwern): The foreach loop is equivalent to this:

my @lines = <$fh>;
for my $line (@lines) {
    ...
}

It’s unfortunate that Perl doesn’t optimize this special case as it does with the range operator (1..10).

For example, if I read /usr/share/dict/words with a for loop and a while loop and have them sleep when they’re done I can use ps to see how much memory the process is consuming. As a control I’ve included a program that opens the file but does nothing with it.

USER       PID %CPU %MEM      VSZ    RSS   TT  STAT STARTED      TIME COMMAND
schwern  73019   0.0  1.6   625552  33688 s000  S     2:47PM   0:00.24 perl -wle open my $fh, shift; for(<$fh>) { 1 } print "Done";  sleep 999 /usr/share/dict/words
schwern  73018   0.0  0.1   601096   1236 s000  S     2:46PM   0:00.09 perl -wle open my $fh, shift; while(<$fh>) { 1 } print "Done";  sleep 999 /usr/share/dict/words
schwern  73081   0.0  0.1   601096   1168 s000  S     2:55PM   0:00.00 perl -wle open my $fh, shift; print "Done";  sleep 999 /usr/share/dict/words

The for program is consuming almost 32 megs of real memory (the RSS column) to store the contents of my 2.4 meg /usr/share/dict/words. The while loop only stores one line at a time consuming just 70k for line buffering.

What’s the safest way to iterate through the keys of a Perl hash?

What’s the safest way to iterate through the keys of a Perl hash?

The rule of thumb is to use the function most suited to your needs.

If you just want the keys and do not plan to ever read any of the values, use keys():

foreach my $key (keys %hash) { ... }

If you just want the values, use values():

foreach my $val (values %hash) { ... }

If you need the keys and the values, use each():


keys %hash; # reset the internal iterator so a prior each() doesn't affect the loop
while(my($k, $v) = each %hash) { ... }

If you plan to change the keys of the hash in any way except for deleting the current key during the iteration, then you must not use each(). For example, this code to create a new set of uppercase keys with doubled values works fine using keys():


%h = (a => 1, b => 2);

foreach my $k (keys %h)
{
    $h{uc $k} = $h{$k} * 2;
}

producing the expected resulting hash:


(a => 1, A => 2, b => 2, B => 4)

But using each() to do the same thing:


%h = (a => 1, b => 2);

keys %h;
while(my($k, $v) = each %h)
{
    $h{uc $k} = $h{$k} * 2; # BAD IDEA!
}

produces incorrect results in hard-to-predict ways. For example:
(a => 1, A => 2, b => 2, B => 8) 

This, however, is safe:


keys %h;
while(my($k, $v) = each %h)
{
    if(...)
    {
        delete $h{$k}; # This is safe
    }
}

All of this is described in the perl documentation:


% perldoc -f keys
% perldoc -f each

There is another caveat with each. The iterator is bound to the hash, not the context, which means it is not re-entrant. For example if you loop over a hash, and print the hash perl will internally reset the iterator, making this code loop endlessly:


my %hash = ( a => 1, b => 2, c => 3, );
while ( my ($k, $v) = each %hash ) {
    print %hash;
}