User:JohnDR/perl

= perl notes =

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.

Basic
$hh{abc}=123; $hh{def}=456; $hh{ghi}=789; foreach $line (keys(%hh)) {   # any changes to hh inside foreach loop will not be taken $hh{jkl}=23;                # That is, jkl will not show up in print print "$line\n"; }
 * foreach note

use Fcntl ':mode'; ($dum,$dum,$mode,$dum,$dum,$dum,$dum,$size,$dum,$mtime)=stat($fname); $mode = S_IMODE($mode)
 * stat


 * "my" is local to the loop/block (not only on the function level).

delete($h{abc});      # deleted $h{abc}=;           # assign undef to element "abc". "abc" still exist. $h{abc}=undef;        # same as $h{abc}=;
 * Deleting a hash element

%{$this->{hipats}}=; my $hipat = \%{$this->{hipats}};      # pointer to the hash $$hipat{abc}=23; print "Orig: $hipat\n"; foreach $line (keys(%{$hipat})) { print "$line\n"; } print "Clearing\n"; %{$this->{hipats}}=;                # clear it, the address is still the same. print "Orig: $hipat\n";               # Same as above foreach $line (keys(%{$hipat})) {     # Result is cleared print "$line\n"; }
 * Clearing a hash element

-e Exist -w Writable -x Executable
 * File checks

if($line=~/(a.*?b)/) { }
 * Avoiding Greedy Expressions

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}
 * References vs Deep Copy

$this->{val} = 453; my $rval = \$this->{val}; my $xxval = \${$this->{val}}; print "$this->{val}\n";       # 453 print "$$rval\n";             # 453 print "$$xxval\n";            # undefined my $nval = \${$this->{nval}}; $$nval = 444; print "$$nval\n";             # 444 print "${$this->{nval}}\n";   # 444 print "$this->{nval}\n";      # SCALAR(0x0000)
 * Hash scalar reference

$rec = { TEXT    => $string, ARY     => [ @aryvariable ], LOOKUP  => { %some_table }, THATCODE => \&some_function, THISCODE => sub { ....code.... },  HANDLE   => \*STDOUT, }
 * Hash of different types

foreach $k (keys(%{$rec->{LOOKUP}})) {  }; print( $rec->{TEXT} ); print( ${$rec}{TEXT} );  # same as above $rec->{THATCODE};      # Call some_function $rec->{THISCODE};      # Call the anonymous function $rf = \&some_function; &$rf;
 * 1) Accessing the hash
 * 1) Function reference

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

foo({arg1=>1, arg2=>2}); exit(0); sub foo { my($harg) = @_; my %h=%{$harg};   # This makes a physical copy of the hash foreach $k (keys(%h)) { print "$k=[$h{$k}]\n"; } }
 * hash as argument

$hy{top}{abc}=1;  # this will not compile during strict! $hy{top}{abc}{key1}=1; $hy{top}{abc}{key2}=2; $hy{top}{def}{key2}=2;
 * hash use:

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

Negative Regex
$line="blah hsw foo bar"; if($line=~/^(?!.*bdw.*)/) { print "case 1 True\n"; } else { print "case 1 False\n"; } $line="fee fi foe fum bdw"; if($line=~/^(?!.*bdw.*)/) { print "case 2 True\n"; } else { print "case 2 False\n"; }
 * Contributor: Dan Phillips

Pointers
push(@ar, \&func1); push(@ar, \&func2); push(@ar, sub { print "i'm in anonymous\n"; } ); &{$ar[1]};  # result: i'm in func2 &{$ar[2]};  # result: i'm in anonymous exit(0);
 * Function pointer

sub func1 { print "i'm in func1\n"; } sub func2 { print "i'm in func2\n"; }

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

.....

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

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
$SIG{'INT'} = 'dokill';   # or "= sub {  }" also works
 * 1) Put this at top of file

....

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.

fork, parent, child code
my $pid = fork; if ($pid) { # parent push(@childs, $pid); } elsif ($pid == 0) { # child local $SIG{INT} = 'IGNORE'; $cmd = "/bin/sleep 10 ; echo \"done sleeping\""; system($cmd ); exit(0); } else { #could not fork }
 * 1) NOTE!!!!!! pls use "package MakeChild" instead!
 * 2) from Joanna H

foreach (@::childs) { waitpid($_, 0); }
 * 1) waiting for child to finish

system vs exit numbers
The following numbers are $res value when $res=system("command");
 * 1) exit(0)  -  0
 * 2) exit(1)  -  256
 * 3) exit(2)  -  512
 * 4) ctrl+c   -  2
 * 5) exit(-1) - 65280
 * 6) die      - 2304

Value of $1 and $2 are retained
if($ARGV[0]=~/(\w+):(\w+)/) { try2($1); try2($2);  # value of $2 is the *real* $2, not the $2 from try2 } exit(0);
 * See example below:

sub try2 { my($var) = @_; print "try2 input: [$var]\n"; if($var=~/(\w)(\w+)/) { print "try2 inside: [$1] [$2]\n"; } }

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

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.

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

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

Object Template
use strict; package Person;
 * 1) OBJECT template
 * 1) OBJECT template

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

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

return($this); }

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

# 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

}

use strict;
 * 1) Inheritance template
 * 1) Inheritance template

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

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);
 * 1) Constructor

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

return($this); }


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

Use and package scope
use strict;
 * Given the following myuse.pm
 * 1) !/usr/intel/bin/perl5.85 -w

package myuse;

my $abc = 123;

sub try1 { print "i'm try1 [$abc]\n"; $abc++; return; }

sub returnabc { return($abc); }

1;

use myuse; main; sub main {
 * See below notes on variable scope on package:

print "i'm in main\n";

#try1; # error, undefined subroutine &myuse::try1;  # valid &myuse::try1;  # valid

print "in main: $myuse::abc\n";  # undefined print "in main via method: ".&myuse::returnabc."\n";

}

package inside a function (used for scoping)
main; foo; mainlocal::foo; exit(0);

sub main { package mainlocal;     # used to localize a group of functions my $var=1; print "I'm in main var=$var\n"; foo;         # this will call local &::fooban;   # this will call main fooban &::foo;      # this will call main foo $var++; print "I'm exiting main\n"; return;

sub foo { print "i'm in local foo var=$var\n";  # accessing $var is illegal (perl only show as warning) } }

sub foo { print "i'm in main foo\n"; } sub fooban { print "i'm in main fooban\n"; }

= Benchmarks =

perl invoke windows vs unix
Windows: 93ms per perl invoke (via system) Windows: 43ms per touch invoke (via system) UNIX:   40ms per perl invoke
 * invoking perl: 1000 system call to perl:

hash format comparison
executed three times: 616148 keys using $$hd:     0.67 sec using $hd->{}:  0.67 sec using ${$hd}:   0.67 sec using direct hh: 0.65 sec

string concatenation
a) $res="$res$txt" # very slow vs b) $res.=$txt       # much faster (more than 3x)

= Unit testing = use strict; use Test;

BEGIN { plan tests => 2, todo => [1] }

ok(func1(1),1);  # this is fail
 * 1) test #1
 * 2) ok;

ok(func1(1),2);  # this is pass exit(0);
 * 1) test #2

sub func1 { my($i) = @_; return($i+1); } 1..2 todo 1; Name "main::ary" used only once: possible typo at /nfs/pdx/home/jqdelosr/perl/notes.pl line 42. not ok 1 ok 2
 * 1) this is the function being tested
 * output:
 * 1) Running under perl version 5.008005 for linux
 * 2) Current time local: Thu Sep  2 10:54:08 2010
 * 3) Current time GMT:   Thu Sep  2 17:54:08 2010
 * 4) Using Test.pm version 1.25
 * 1) Test 1 got: "2" (notes.pl at line 18 *TODO*)
 * 2)   Expected: "1"
 * 3)  notes.pl line 18 is: ok(func1(1),1);


 * Reference: http://perldoc.perl.org/Test.html

= Others =

Max perl require size - 5.0MB

 * see tvpvhelp#21302 for details

jen

 * jen is a function to encode.