$Id$ Important lines prefixed by '[!](?:(?!\s)| )'. General (non-Perl) lines prefixed by '[~](?:(?!\s)| )'. Perl general knowledge from docs prefixed by '[#](?:(?!\s)| )'. Perl-5.0+ header: ! #! /usr/bin/perl -w # # $Id$ package My::Package::Name; ! use vars qw($VERSION); ! # $VERSION=do { my @r=(q$Revision$=~/\d+/g); sprintf "%d.".("%03d"x$#r),@r; }; ! use strict; #use warnings; * Note 'sprintf' hack to keep Perl MakeMaker numbering linear with CVS. * Always using 'strict'/'warnings' * Not sure if one has right to declare own non-CPAN-accepted package name outside of 'My::' prefix, recently using always rather 'My::' Perl-5.6.0+ header: ! #! /usr/bin/perl # # $Id$ package My::Package::Name; ! # our $VERSION=do { my @r=(q$Revision$=~/\d+/g); sprintf "%d.".("%03d"x$#r),@r; }; ! use strict; ! use warnings; Header block for OO files and/or exporting files: require My::Inherited1; require My::Inherited2; require Exporter; use vars qw(@ISA @EXPORT); @ISA=qw(My::Inherited1 My::Inherited2 Exporter); @EXPORT=qw(); Generally always rather 'require' than 'use'. Modules with non-conflicting naming are 'use'd (such as 'MIME::Base64' with &encode_base64 etc.). Method parenthesis: ! * Always given if no arguments are passed. ! * Always given for any object or class method calls. ! * Always given if the first arguments looks as bless()ed. * docs/comments: 'method()' used for invocation, '&method' for reference ! * Always given for 'map', 'each' (commands-not methods from previous line) * Trying to prevent if not neccessary ! * Usually needed for 'print' argument as its first arg already has '()' ! * Never using 'method_name blessed_object' syntax: Dangerous: name blessed_object interpreted as blessed_object->name() instead of intended name(blessed_object) Always use named control variable for 'for my $var (...)' if the naming makes sense, leave the default '$_' instead of common names such as $i or $n. Function header: # $first_arg,%$secondarg,@rest sub function_name { my($class,first_arg,$secondarg,@rest)=@_; * Comment-line suppressed if trivial. * Comment-line written in the dereferencing operators order being used for accessing elements. ! * Suicide imminent if '=@_' forgotten. * Always used $class or $self for class-methods or object-methods. * Usually not using (caller should call it manually): $self=$self->new() if !ref $self; ! * Never modifying @_ to keep perl debugger 'T' command happy * Wanna use function prototypes (not yet) although I will never use '\', '*' or '&' for the same reasons I would never use C++ '&' param. Not using: 'unless'(->'if !'), 'until'(->'while !'), 'foreach'(->'for'). Always trying to use 'map' instead of 'for'. Nested 'map's are fined although $_ renaming is needed there: map({ ! my $whole_record=$_; map({ $_+$whole_record->{"shift_value"}; } ($whole_record->{"list"})); } @some_record_list) Always trying to place 'for'/'if'/'while' after the command (without block). * Impossible if multiple modifiers needed (just one placed after): ! print "$_\n" for (0..5) if $do_print; * Impossible if using variable declared in the modifier: ! print "$var\n" for my $var (@some_array); * Sometimes even using for multiple commands under the control: do { print "kaboom"; return; } if $serious_problem; do not use this as even 'print' can fail: print "kaboom" and return if $serious_problem; (and it uses unclear precedence rules) OO constructor always named &new or &new_*. Utility functions without any OO sense do not use $class or $self. Rather referrencing rvalue than dereferrencing lvalue: @{$ref->{"array"}}=(1,2,3); never used, I like rather: $ref->{"array"}=[1,2,3]; Lists parenthesed where passed as 'list' argument: map({ some_function_body; } listarg1,listarg2); never used, I like rather: map({ some_function_body; } (listarg1,listarg2)); * parentheses suppressed if simple '@array_name' is passed. Last command of block { } always suffixed by its ';'. String substitution used only for simple scalars, concatenation used otherwise: print "total_crashes: $left or $maybe->{'crashes'}\n"; never used, I like rather: print "total_crashes: $crashes or ".$maybe->{'crashes'}."\n"; Conditional expressions 'a?b:c' usually use the same item $record->{"field"}==5 ? 7 : $record->{"field"}+1 can be nicely rewritten as: ! map(($_==5 ? 7 : $_+1),$record->{"field"}) while() modifies $_ without its localization! Needed everywhere: ! # local $_; while () { some_commands; } Never used barewords for hash keys, always quoted: $hashref->{somekey} never used, I like rather: ! $hashref->{"somekey"} as it can crash for some reseverd words used as 'somekey'. You cannot use positive-case substitution in list context: @list=($user_wishes{"provide_arg"} && "real_arg"); does '@list=(undef()); @list==1; #YES' if !$user_wishes{"provide_arg"}, instead you must code the full ugly construction: ! @list=(!$user_wishes{"provide_arg"} ? () : ("real_arg")); ~ Conditional-evaluation always shortcut optimized by providing the trivial case as the first one of two branches (even if such trivial branch has more source code letters to write). @new_list=(!@list ? (list_is_empty(\@list)) : @list); although sometimes the meaning of 'trivial case' can be subjective. # Private methods named as &_method (still must be called as _method()!). ~ Value being prepared for return named 'r'. It may get handy to use: confess if !wantarray() && 2<=@r; # optional and sometimes not appropriate return wantarray() ? @r : $r[0]; Never using 'die' or 'warn', always 'confess' or 'cluck' (and never 'carp' or 'cloak'): use Carp qw(cluck confess); Always local()ize file handle globref if not in package 'main': ! local *F; do { open F,$_ or confess "$_: $!"; } for ("some_file"); There are many ways to code 'C switch(){}', I use: if (cond1) { } elsif (cond2) { } else { } although it is deprecated by Perl doc but they do not give much better solutions. Some of them are restricted to single command body ('do {}' needed) etc. if-elsif-else method would be shorter in the code if } elsif (condX) { indenting style is used. ~ Function definitions ordered lower->higher to prevent pre-declarations. ! For any non-trivial data structures it is essential to differentiate between: scalar, list, array, hash, ref to scalar, ref to array, ref to hash Any missing trailing function parameters appear as undef(). Any passed trailing undef()s can still be properly detected and interpreted: scalar(@_) will still report the real number of parameters. undef() is the real parameter. Perl is too damn slow during startup but it is blazingly fast when it runs. mod_perl prevents this startup overhead (present in standalone Perl CGIs). 'Storable'-disk-dumped complex memory data structures are 10x larger in memory as reported by http://petamem.com . Curly-bracketing all subexpressions for dereferencign explicitely if not trivial: my %rec=("x"=>["a\n","b\n"]);print @$rec{"x"}; print @$arrayref; would not work as it would mean: my %rec=("x"=>["a\n","b\n"]);print @{$rec}{"x"}; print @$arrayref; , I like rather even if it would work without curly-bracketing: ! my %rec=("x"=>["a\n","b\n"]);print @{$rec{"x"}}; print @$arrayref; Declaration scope of 'my' in the non-sub{} file: Whole file inside one package. Declaration scope of 'my' in sub{} or block {}: Only in { }, not accessible by callees. Declaration scope of 'local': This sub{} and globally for all callees. * Perfect for some nesting counters: my $func_nest=0; sub func { # automatically restored after exit from &func local $func_nest=$func_nest+1; } * Built-in variables cannot be 'my' scoped, use 'local' instead Declaration scope of 'our'(5.6.0+) or 'use vars...': Global across packages. (These scoping rules are simplified but works4me.)