User:JohnDR/perl

From Wikipedia, the free encyclopedia

Contents

[edit] perl notes

[edit] Programming Style

  • Do not use "package::foo();" directly. Must use objects. Using package::foo() is non-object.
Even if the object is only used once "$::g_res = new Objx();"
  • Always create a main() subroutine to avoid global conflicts.

[edit] Basic

  • stat
use Fcntl ':mode';
($dum,$dum,$mode,$dum,$dum,$dum,$dum,$size,$dum,$mtime)=stat($fname);
$mode = S_IMODE($mode)
  • "my" is local to the loop/block (not only on the function level).
  • Deleting a hash element
delete($h{abc});       # deleted
$h{abc}=();            # assign undef to element "abc". "abc" still exist.
$h{abc}=undef;         # same as $h{abc}=();
  • File checks
-e Exist
-w Writable
-x Executable
  • Avoiding Greedy Expressions
if($line=~/(a.*?b)/) { }
  • References vs Deep Copy
my %hcopy = %{$john->{h}};   # This is not a reference. Performs a deep copy.
my $hr=\%hh;                 # This is a reference. Same as: $hr={ key=>val, key1=>val1, };
${$hr}{key}="new";           # same as $hh{key}
  • Hash of different types
 $rec = {
   TEXT     => $string,
   ARY      => [ @aryvariable ],   
   LOOKUP   => { %some_table },
   THATCODE => \&some_function,
   THISCODE => sub { ....code.... },
   HANDLE   => \*STDOUT,
 }

 # Accessing the hash
 foreach $k (keys(%{$rec->{LOOKUP}})) {   };
 print( $rec->{TEXT} );
 print( ${$rec}{TEXT} );   # same as above
 
 # Function reference
 $rec->{THATCODE}();       # Call some_function()
 $rec->{THISCODE}();       # Call the anonymous function
 $rf = \&some_function;
 &$rf();
  • Sorting
String:       sort( { $a cmp $b } @arr );    # just reverse $a and $b for reverse. Default is string.
Numeric:      sort( { $b <=> $a } @arr );
sort by keys: sort( keys( %hh ));
sort by values (return the keys):
    sort( { $hh{$a} <=> $hh{$b} } keys(%hh) );

[edit] Modules

  • Basename
use File::Basename;
$fname   = &File::Basename::basename($path);
$dirname = &File::Basename::dirname($path);
  • Cwd
use Cwd;
print cwd();

[edit] Goodie Stuff

  • Trap uninitialized:
# Put this at top of file
$SIG{__WARN__} = sub { for ($_[0]) { &process_warn_subr; } };   # trap uninitialized values

.....

# die out if uninitialized warning happens
sub process_warn_subr {
  package process_warn_subr;
  my @c = caller(1);

  if(/Use of uninitialized value/i) {
    print "ERROR: perl uninitialized value access detected in $0:\n";
    print "-e- => package: $c[0]\n";
    print "-e- => file   : $c[1]\n";
    print "-e- => line   : $c[2]\n";

    ;# promote warning to a fatal version
    die "-e- => trap: $_";
  } else {
    ;# other warning cases to catch go here
    warn "-w- => trap: $_";
  }

}
  • Trap Ctrl+C
# Put this at top of file
$SIG{'INT'} = 'dokill';    # or "= sub {  }" also works

....

sub dokill {
  die("Ctrl+C happened\n\n");      # pressing ctrl+c while inside dokill() has no effect.
}  # NOTE: All DESTROY object routines are called here.

[edit] Objects

  • Usage example
use Person;
my $john=new Person("John", "Male");

print Person::direct()."\n";    # Access "static" methods directly
print $john->{NAME}."\n";       # Retrieves the {NAME} property.
print $john->name."\n";         # Calls the name() method. $john->name() is the same

print @{$john->array};          # Array access
print %{$john->hash};           # Hash access

$john=();    # calls the destructor.

  • Object that contain hash
package Data;
sub new {
  my ($class)=@_;
  my $this = {};
  bless($this, $class);

  my $hs = {};
  $hs->{data1}=33;       # information hash
  $hs->{data2}=35;

  $this->{dd}=$hs;       # Assign it
  $this->{tag}="TAG";

  return($this);
}


package UserObject;
sub new {
  my ($class)=@_;
  my $this = {};
  bless($this, $class);

  $this->{obj} = new Data();

  my $all = $this->{obj}->{dd};     # Access the hash of the Data object
  my $line;
  foreach $line (keys(%{$all})) {   # Reference way
    print "$line ${$all}{$line}\n";
    ${$ali}{$line}+=100;            # increment it
  }
  foreach $line (keys(%{$this->{obj}->{dd}})) {        # Direct way
    print "$line ".${$this->{obj}->{dd}}{$line}."\n";  # Incremented value is seen here
  }

  return($this);
}

[edit] Object Template

# =============================================================
# OBJECT template
# =============================================================
use strict;
package Person;

# Constructor
sub new {
  my ($class, $name, $sx)=@_;    # 1st arg is always the classname ($class=="Person")
  my $this = {};
  bless($this, $class);

  $this->{NAME} = $name || ();    # Property
  $this->{AGE}  =  3;
  $this->{SEX} = $sx;             # same as $$this{SEX}, $this->{SEX}

  return($this);
}

# Methods
sub peers {
  my($this, @peer) = @_;

  # alias all properties to be used
  my $PEER = \@{$this->{PEER}};
  my $SEX  = \$this->{SEX};
  my $HH   = \%{$this->{hh}};            # Access by ${$HH}{...}
  my $AA   = \@{$this->{ary}};           # Access by $$AA[..]

  $this->SUPER::method();                 # to access the base method

  if($#peer>=0) {
    push(@{$$PEER}, @peer);
  }
  return($$PEER);
}

sub direct {            # Can be accessed from main directly via: Person::direct(). However, don't call methods directly! (violation to programming style)
  return($static_sex);
}

sub DESTROY {
  print("I'm doing destructor\n");
  # NOTE: DESTROY is not called if ctrl+C happened. Add the following line in the constructor:
  # $SIG{'INT'} = sub { die("Ctrl+C happened\n\n"); } ;    # This is necessary for DESTROY to be called even if Ctrl+C

}

# =============================================================
# Inheritance template
# =============================================================
use strict;

package Person2;
use obj;                # The base obj. Remove this if the base obj is on the same file
use vars qw(@ISA);
@ISA = ("Person");      # inherits from Person

# Constructor
sub new {                             # ok to inherit as long as it is not on main file.
  my ($class, $n, $s, $job)=@_;       # 1st arg is always the classname
  my $this = new Person($n, $s);      # same as $class->Person::new($n, $s);
  bless($this, $class);

  .....  # e.g.  $$JOB = $job;

  return($this);
}

; # override any methods that needed to be overridden...

[edit] Benchmarks

  • invoking perl: 1000 system call to perl:
Windows: 93ms per perl invoke (via system)
Windows: 43ms per touch invoke (via system)
UNIX:    40ms per perl invoke