Perl Sub

extern: top | index
intern: preamble | sub | dereferencing | end

Preamble

A function in Perl is called a subroutine, or a 'sub'. Perl subroutines can be defined as either named or anonymous subroutines. A named subroutine can be declared and defined anywhere in a Perl script, using the syntax:

sub NAME[($)] { BLOCK; }

Where NAME is the name you select for your subroutine, and BLOCK is the actual programming logic, surrounded by curly braces ({...}).
 


top

sub - A perl Function:

Named Subroutines

A subroutine, a 'sub' in Perl, is a code function that can do work on 1 or more parameters passed, or on global variables, and may return an item, or an array, or ... a subroutine called say 'trim_line' can be called through :-

code:

trim_line( "Dan" );
trim_line "Dan";
&trim_line( "Dan" );
&trim_line;

In the first 3 cases the literal string, "Dan" is passed to the function. The first is the most common, and the trim_line{ ... } function can be declared anywhere in the script, while the second can be ambiguous to the script parser, so the subroutine must be declared before this statement. The second two are the same, except any prototyping is disabled, by the '&' in front of the function name, and in the last case, the special '@_' global array will be passed, with whatever it contains at that moment.

Here is a simple function, to trim a line - remove trailing CR or LF characters, convert tabs, symbolically \t, to a space, convert double spaces to single spaces, remove leading white space, and trailing white space ... that is really TRIM the line ... and return the 'trimmed' results...

code:

sub trim_line($) {
   my ($ln) = shift;  
   chomp $ln; # remove LF, if present  
   $ln =~ s/\r$//; # and remove CR, if present  
   $ln =~ s/\t/ /g; # convert tabs, \t, to a space  
   $ln =~ s/\s\s/ /g while ($ln =~ /\s\s/); # double spaces to 1
   $ln = substr($ln,1) while ($ln =~ /^\s/); # leading spaces  
   $ln = substr($ln,0,length($ln)-1) while (($ln =~ /\s$/)&&(length($ln)));
   return $ln;
}
$line = "     \tthis   line    \r\n";
print   '['.trim_line($line)."]\n";

output:

[this line]

Yes, it is HARD to show what HIDDEN, or non-visible characters were changed ... but the trailing CF,LF has been removed, the tab to a space, multiple spaces to a single, and leading white space removed ... a 'trimmed' line - much better for parsing ... Here is an even simpler function, a sub, to trim a line, just removing 'space' type characters from the beginning and end of the string passed :-

code:

sub trim {
   my $string = shift;  
   for ($string) {
     s/^\s+//;
     s/\s+$//;
   }
   return $string;
}

The above subs show a single parameter passed, so shift was used to get the value into a local variable, my $ln ... this local $ln was massaged, and returned by the function ... multiple parameters can also be passed, and they are collected into local variables by using the following -

code:

sub find_item {
   my ($find, @list) = @_; # get the passed parameters  
   my   @fnd = (); # initialise a blank array to return  
   foreach my $i (@list) { # interate through the list  
      if ( $i eq $find ) {
         push(@fnd, $i); # push this item onto the array
      }
   }
   return   @fnd;
}

Take care - this is a meaningless function ;=() - for a start there are many other ways to 'find' something in an array, and why would you want to return an array containing just a list of what you are trying to find ... but is shows that parameters, including arrays, can be passed, but the ARRAY item passed MUST be last in the my (...) list ...

Generated Named Subroutines

It is also possible to 'generate' a set of named functions, like the following sample, but note strict reference has to be disabled to allow the symbol table to be modified :-

code:

# auto-generate a set of functions
my @TTColors = qw( red green blue white );
for $name (@TTColors) {
   no strict 'refs'; # allow symbol table manipulation  
    *$name = *{uc $name} = sub { "<tt class=\"$name\">@_</tt>"; }
}

And to use these auto-generated functions, in this case indirectly, that is call through a variable holding the function, like -

code:

print "Colours\n"; # output the colours
foreach $name (@TTColors) {
   my $func = \&$name; ## get the function - the auto-generated sub  
   $txt = $func->($name); # surround/encase the text  
   print "[";
   print $txt;  
   print "]";
   print "\n";
}

output:

Colours
  [red]
  [green]
  [blue]
  [white]

The above also shows 'dereferencing', see the '->' in the $func->($name); to call a function reference. Here is another example of a 'reference' to a subroutine, passed to another subroutine in a hash reference :-

code:

sub foo($) {
    my ($v) = @_;
    prt("Foo called, with [$v]\n");
}
sub test2($) {
    my ($rp) = @_;
    my $foo = ${$rp}{'FUNCTION'};
    $foo->("Message");
}
sub test1() {
    my %hash = ();
    my $rh = \%hash;
    ${$rh}{'FUNCTION'} = \&foo;
    test2($rh);
}

output:

Foo called, with [Message]

Also note the use of the '&', in '\&foo', meaning to disable prototype checking under 'strict', or else the compiler will complain.


top

EOF - perl_sub.htm

checked by tidy  Valid HTML 4.01 Transitional