Recursion

advertisement
533554356
-1-
Chapter 6
Subroutines in Perl
Built-in Math Functions
User defined Subroutines
Argument Lists
Returning values
Other Ways to invoke a subroutine
Random number generation
Recursion
Scope Rules: Global, Lexical and Dynamic
Namespaces, Packages and Modules
Pragmas
533554356
-2-
Built in functions/subroutines and user defined functions/subroutines
Built in function are functions that are part of the Perl programming environment
The unix command man perlfunc or perldoc perlfunc on other systems allow
you to view the documentation of Perl functions.
The programmer can write her/her own subroutines. Each subroutine should
perform a single task – ( functional cohesion )
Built in Math functions ( pg. 174)
Built in math library functions allow the programmer to perform common mathematical
calculations.
$result = sqrt ( 900 );
Arguments to the function can be scalars, hashes, arrays or expressions.
#!/usr/bin/perl
# Fig. 6.3: fig06_03.pl
# Demonstrating some math functions.
$_ = -2;
print "Absolute value of 5 is: ", abs( 5 ), "\n",
"Absolute value of -5 is: ", abs( -5 ), "\n",
"Absolute value of $_: ", abs, "\n\n";
print "exp( $_ ): ", exp, "\n";
print "log( 5 ): ", log( 5 ), "\n";
print "sqrt( 16 ): ", sqrt( 16 ), "\n";
Output:
Absolute value of 5 is: 5
Absolute value of –5 is: 5
Absolute value of –2: 2
exp( -2 ): 0.135335283236613
log( 5): 1.60943769124341
sqrt(16 ): 4
533554356
-3-
#!/usr/bin/perl
# Fig 6.4: fig06_04.pl
# User-defined subroutines that take no arguments.
subroutine1(); # call the subroutine with no arguments
subroutine2(); # call the subroutine with no arguments
# the code after this comment executes only if the program
# explicitly calls (or invokes) these subroutines (as in lines 5 and 6).
sub subroutine1
{
print "called subroutine1\n";
}
sub subroutine2
{
print "called subroutine2\n";
}
Output:
called subroutine1
called subroutine2
Argument List
#!/usr/bin/perl Fig 6.5: fig06_05.pl
# Demonstrating a subroutine that receives arguments.
displayArguments( "Sam", "Jones", 2, 15, 73, 2.79 );
# output the subroutine arguments using special variable @_
sub displayArguments
{
# the following statement displays all the arguments
print "All arguments: @_\n";
# uses special array variable @_
# the following loop displays each individual argument
for ( $i = 0; $i < @_; ++$i ) {
# accesses each element in the array @_– no relationship to $_ special variable
print "Argument $i: $_[ $i ]\n";
}
}
533554356
-4-
Output:
All arguments: Sam Jones 2 15 73 2.79
Argument 0: Sam
Argument 1: Jones
Argument 2: 2
Argument3: 15
Argument4: 73
Argument5: 2.79
@_ displays each argument separated by a space
@_ flattens all arrays and hashes. It will contain one list with all the data from the array
and the scalar value. A hash is flattened into a list of its key/value pairs.
( @first, $second ) = @_;
@first will take all the data and $second will be undefined.
The subroutine displayArguments can receive any number or arguments.
533554356
-5Returning values
A subroutine returns a value using the return keyword.
#!/usr/bin/perl
# Fig 6.7: fig06_07.pl
# Demonstrating a subroutine that returns a scalar or a list.
# call scalarOrList() in list context to initialize @array, then print the list
@array = scalarOrList(); # list context to initialize @array
$" = "\n";
# set default separator character – special variable $”
# specifies what will be printed between values in array
# when an array is printed in double quotes “”
print "Returned:\n@array\n";
# call scalarOrList() in scalar context and concatenate the
# result to another string
print "\nReturned: " . scalarOrList(); # scalar context
# use wantarray to return a list or scalar
# based on the calling context
sub scalarOrList
{
if ( wantarray() ) { # if list context
return 'this', 'is', 'a', 'list', 'of', 'strings';
}
else {
# if scalar context
return 'hello';
}
}
Output:
returned:
this
is
a
list
of
strings
Returned: hello
533554356
-6-
Other ways to call a subroutine: (Page 181)
&subroutine1;
# prefix & calls subroutine1
Using this syntax the parenthesis can be omitted it there are no arguments or if the
subroutine the default arguments in @_
Parenthesis are always required if explicit arguments are passed
Another syntax is for calling subroutines is the bareword.
subroutine1;
In this case, if the subroutine is defined before the line executed the subroutine will be
called. If it is not defined - the subroutine is not called and the call is interpreted as a
string. I the subroutine would return something the string would be interpreted as the
return value.
533554356
-7-
#!usr/bin/perl Fig 6.8: fig06_08.pl
# Syntax for calling a subroutine.
# subroutine with no arguments defined before it is used
sub definedBeforeWithoutArguments
{
print "definedBeforeWithoutArguments\n";
}
# subroutine with arguments defined before it is used
sub definedBeforeWithArguments
{
print "definedBeforeWithArguments: @_\n";
}
# calling subroutines that are defined before use
print "------------------------------\n";
print "Subroutines defined before use\n";
print "------------------------------\n";
print "Using & and ():\n";
&definedBeforeWithoutArguments();
&definedBeforeWithArguments( 1, 2, 3 );
print "\nUsing only ():\n";
definedBeforeWithoutArguments();
definedBeforeWithArguments( 1, 2, 3 );
print "\nUsing only &:\n";
&definedBeforeWithoutArguments;
print "\"&definedBeforeWithArguments 1, 2, 3\"", " generates a syntax error\n";
print "\nUsing bareword:\n";
definedBeforeWithoutArguments;
definedBeforeWithArguments 1, 2, 3;
# calling subroutines that are not defined before use
print "\n-----------------------------\n";
print "Subroutines defined after use\n";
print "-----------------------------\n";
print "Using & and ():\n";
&definedAfterWithoutArguments();
&definedAfterWithArguments( 1, 2, 3 );
print "\nUsing only ():\n";
definedAfterWithoutArguments();
definedAfterWithArguments( 1, 2, 3 );
533554356
-8-
print "\nUsing only &:\n";
&definedAfterWithoutArguments;
print "\"&definedAfterWithArguments 1, 2, 3\"", " generates a syntax error\n";
print "\nUsing bareword:\n";
definedAfterWithoutArguments;
print "\"definedAfterWithoutArguments\" causes no action\n";
print "\"definedAfterWithArguments 1, 2, 3\"", " generates a syntax error\n";
# subroutine with no arguments defined after it is used
sub definedAfterWithoutArguments
{
print "definedAfterWithoutArguments\n";
}
# subroutine with arguments defined after it is used
sub definedAfterWithArguments
{
print "definedAfterWithArguments: @_\n";
}
533554356
-9-
Output:
-----------------------------Subroutines defined before use
-----------------------------Using & and ():
definedBeforeWithoutArguments
definedBeforeWithArguments: 1 2 3
Using only ():
definedBeforeWithoutArguments
definedBeforeWithArguments: 1 2 3
Using only &:
definedBeforeWithoutArguments
"&definedBeforeWithArguments 1, 2, 3" generates a syntax error
Using bareword:
definedBeforeWithoutArguments
definedBeforeWithArguments: 1 2 3
----------------------------Subroutines defined after use
----------------------------Using & and ():
definedAfterWithoutArguments
definedAfterWithArguments: 1 2 3
Using only ():
definedAfterWithoutArguments
definedAfterWithArguments: 1 2 3
Using only &:
definedAfterWithoutArguments
"&definedAfterWithArguments 1, 2, 3" generates a syntax error
Using bareword:
"definedAfterWithoutArguments" causes no action
"definedAfterWithArguments 1, 2, 3" generates a syntax error
533554356
- 10 Random Number Generation
rand
the function rand will generate a floating-point scalar value greater than or
equal to 0
$i = rand( );
to set the range we can pass the function an argument.
1 + int ( rand ( 6 ) )
using 1 as the shift value and 6 as the scale factor would
produce a number in the range from 1 to 6 by adding 1 to the result.
Otherwise the range would have been 0 to 5.
srand
the function srand lets the system determine seed. It courses the system to
read the system clock to obtain the value for the seed. You can pass an
argument to the function and work with different seeds.
If the function is used it needs only to be called once in the program.
533554356
- 11 -
Recursion
A recursive subroutine is a subroutine that calls itself either directly or through another
subroutine.
#!/usr/bin/perl
# Fig 6.13: fig06_13.pl
# Recursive factorial subroutine
# call function factorial for each of the numbers from
# 0 through 10 and display the results
foreach ( 0 .. 4 ) {
print "$_! = " . factorial( $_ ) . "\n";
}
# factorial recursively calculates the factorial of the argument it receives
sub factorial
{
my $number = shift; # get the argument
if ( $number <= 1 ) { # base case
return 1;
}
else {
# recursive step
return $number * factorial( $number - 1 );
}
}
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
Recursion and iteration – Any recursive algorithm can be coded as an iteration.
To examine whether to use recursion or iteration you can draw the recursion tree.
If the tree is linear it is more efficient to use iteration.
If the tree is balanced ( an no duplicate work is performed ) recursion could be used.
533554356
- 12 Scope Rules: Global, Lexical and Dynamic
An identifier’s scope is the portion of the program in which the identifier can be
referenced.
Three scopes for an identifier are:
Global scope, lexical scope and dynamic scope.
Global Scope:
An identifier of global scope can be used throughout the program. For example:
All global variables have global scope.
Variables identified without any keyword prefix are automatically of global scope
The prefix our can be used to explicitly define global variables
Lexical Scope:
A lexical scope variable is a variable that exists only during the block in which it
was defined.
Prefix: my
Dynamic Scope:
A variable of dynamic scope is one that exists from the time it is created until the
end of the block in which it was created. Such a variable is accessible both in the block
in which it is defined and to any other subroutine called from that block.
Prefix: local
Lexical and dynamic variables always hide ( but do not destroy) global variables of the
same name.
533554356
- 13 -
#!/usr/bin/perl Fig. 6.16: fig06_16.pl Demonstrating variable scope.
# before global variables are defined, call subroutine1
print "Without globals:\n";
subroutine1();
# define global variables
our $x = 7;
our $y = 17;
# call subroutine1 to see results with defined global variables
print "\nWith globals:";
print "\nglobal \$x: $x";
print "\nglobal \$y: $y\n";
subroutine1();
print "\nglobal \$x: $x";
print "\nglobal \$y: $y\n";
subroutine2();
# subroutine1 displays its own $x (lexical scope )
# and $y (dynamic scope) variables, then calls subroutine2
sub subroutine1{
my $x = 10;
local $y = 5;
print "\$x in subroutine1: $x\t(lexical to subroutine1)\n";
print "\$y in subroutine1: $y\t(dynamic to subroutine1)\n";
subroutine2();
}
# subroutine2 displays global $x and subroutine1's $y which has dynamic scope
sub subroutine2
{
print "\$x in subroutine2: $x\t(global)\n";
print "\$y in subroutine2: $y\t(dynamic to subroutine1)\n";
}
Without globals:
$x in subroutine1: 10
$y in subroutine1: 5
$x in subroutine2:
$y in subroutine2: 5
(lexical to subroutine1)
(dynamic to subroutine1)
(global)
(dynamic to subroutine1)
With globals:
global $x: 7
global $y: 17
$x in subroutine1: 10
$y in subroutine1: 5
$x in subroutine2: 7
$y in subroutine2: 5
(lexical to subroutine1)
(dynamic to subroutine1)
(global)
(dynamic to subroutine1)
global $x: 7
global $y: 17
$x in subroutine2: 7
$y in subroutine2: 17
(global)
(dynamic to subroutine1)
533554356
- 14 Namespaces, Packages, and Modules
Perl uses packages ( or namespaces) to determine the accessibility of variables and
subroutine identifiers.
Perl’s scooping rules derive from the package concept.
Each Package has its own symbol table – containing the variables and subroutine names
By default, the global variables and subroutines are part of the main package symbol
table – Perl’s global variables are not true global variables (they are package global
variables, or package variables).
The main package is the default package
Lexical variables – are not part of the symbol table. Each block has its own temporary
storage for lexical variables known as the scratchpad.
A symbol table is a hash that identifies the key (variable) and the value ( address ) of the
variable.
Thus, variable names have to be unique except when they are of different types
( scalar vs. array for example).
533554356
- 15 -
Defining a package and importing it with require
If no package is specified the name of the current package is the default package main
The programmer can change that with the package statement.
Creating a new package causes perl to create a new symbol table.
Normally there is one package per sourcefile. If a program contains two or more
packages each package contains its own unique set of identifiers.
require
is the keyword that tells Perl to locate a package and add it to the program.
.pm is optional – Perl assumes .pm filename extension. Ex:
require
firstPackage;
Perl looks for the file in the current directory – if it cannot find it it
Searches the directories that are named in a special built in array
@INC which contains the directories for the Perl library on the computer.
Packages using require are loaded during the execution phase
::
The :: is the scope resolution operator – it ties the variable on the right to
the package (scope) identified on the left of the ::
533554356
- 16 -
#!usr/bin/perlFig 6.17: fig06_17.pl Demonstrating packages.
# make FirstPackage.pm available to this program
require FirstPackage;
# define a package global variable in this program
our $variable = "happy";
# display values from the main package
print "From main package:\n";
print "\$variable = $variable\n";
print "\$main::variable = $main::variable\n";
# display values from FirstPackage
print "\nFrom FirstPackage:\n";
print "\$FirstPackage::variable = $FirstPackage::variable\n";
print "\$FirstPackage::secret = $FirstPackage::secret\n";
# use a subroutine in FirstPackage to display the
# values of the variables in that package
FirstPackage::displayFirstPackageVariables();
From main package:
$variable = happy
$main::variable = happy
From firstPackage:
$FirstPackage::variable = birthday
$FirstPackage::secret =
$variable in displayFirstPackagevariables = birthday
$secret in displayFirstPackageVariables = new year
533554356
- 17 -
#!usr/bin/perl Fig 6.18: FirstPackage.pm Our first package.
package FirstPackage; # name the pacakge/namespace
# define a package global variable
our $variable = "birthday";
# define a variable known only to this package
my $secret = "new year";
# subroutine that displays the values of the variables in FirstPackage
sub displayFirstPackageVariables
{
print "\$variable in displayFirstPackageVariables = ", $variable, "\n";
print "\$secret in displayFirstPackageVariables = ", $secret, "\n";
}
533554356
- 18 -
Modules and the use Statement - A module is a package providing the user more
control on how to reference identifies in the module’s package.
use
- is a statement that imports modules and packages at compile time and
the identifiers of the module are available to the program.
- Another advantage is that the compiler can tell us if the package is
available at compile time as opposed to execution time
#!/usr/bin/perl Fig 6.19: fig06_19.pl program to use our first module
use FirstModule; # import identifiers from another package
print "Using automatically imported names:\n";
print "\@array contains: @array\n"; # @FirstModule::array
greeting();
# FirstModule::greeting
Output:
Using automatically imported names:
@array contains: 1 2 3
Modules are handy!
#!/usr/bin/perl Fig 6.20: FirstModule.pm - Our first module.
package FirstModule;
# the following two lines allow this module to export its
# identifiers for use in other files.
use Exporter;
# use module Exporter
our @ISA = qw( Exporter ); # this module "is an" Exporter
# @array and &greeting are imported automatically into a
# file that uses this module
our @EXPORT = qw( @array &greeting );
# define identifiers for use in other files
our @array = ( 1, 2, 3 );
sub greeting
{
print "Modules are handy!";
}
return 1; # indicate successful import of module
533554356
- 19 -
Pragmas - Perl pragmas are statements that the compiler uses to set compiler options.
use strict;
use strict ‘subs’;
use strict ‘vars’;
use vars qw(variable1 variable2 variable2) ;
using use strict makes programs easier to maintain and debug. When using use strict
Perl checks each variable to make sure it is fully qualified,. There are four ways use
strict can be satisfied:
a) use the my keyword for lexical scope – then you can use their short name
throughout the block in which they are defined
b) use our keyword - package variables defined with our keyword are placed in
the symbol table. They can be accessed with their short name throughout the
package. Outside the package they must be accessed with their fully qualified
name.
c) variables can be used with their fully qualified name in all instances.
Including in the package in which they are defined. $main::variable
d) a program can specify a use vars statement followed by a list containing the
names of variables
use vars qw( variable1 variable2 variable3 );
use warnings;
This pragma warns the user of possible typos, the use of uninitialized variables,
and other problems in the code.
no strict;
no warning;
Turns off strict and warnings. If used inside a block it turns off the strict and
warning until the end of the block.
Named constants:
use constant PI => 3.14159;
use diagnostics;
provides detailed error messages.
enable()
disable()
these command toggle diagnostics on and off during program execution.
use integer;
tells the compiler to perform all arithmetic operations as integer
operations.
Download