Web Development

  Homes arrow Web Development arrow Professional Perl Part 1 - Subroutines
 Webmaster Tools
 
Base64 Encoding 
Browser Settings 
CSS Coder 
CSS Navigation Menu 
Datetime Converter 
DHTML Tooltip 
Dig Utility 
DNS Utility 
Dropdown Menu 
Fetch Content 
Fetch Header 
Floating Layer 
htaccess Generator 
HTML to PHP 
HTML Encoder 
HTML Entities 
IP Convert 
Meta Tags 
Password Encryption
 
Password Strength
 
Pattern Extractor 
Ping Utility 
Pop-Up Window 
Regex Extractor 
Regex Match 
Scrollbar Color 
Source Viewer 
Syntax Highlighting 
URL Encoding 
Web Safe Colors 
Forums Sitemap 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
WEB DEVELOPMENT

Professional Perl Part 1 - Subroutines
By: Developer Shed
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating:  stars stars stars stars stars / 0
    2004-04-19

    Table of Contents:

    Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     

    SEARCH DEV MECHANIC

    TOOLS YOU CAN USE

    advertisement

    Professional Perl Part 1 - Subroutines
    by Wrox Books

    There are two types of subroutine, 'named' and 'anonymous'. Most subroutines are of the 'named' persuasion. These do not have a name by which they can be called, but are stored and accessed through a code reference. Since a code reference is a scalar value, it can be passed as a parameter to other subroutines.

    The use of subroutines is syntactically the same as the use of Perl's own built-in functions. We can use them in a traditional function-oriented syntax (with parentheses), or treat them as named list operators. Indeed, we can override and replace the built-in functions with our own definitions provided as subroutines through the use of the use subs pragma.

    Subroutines differ from ordinary bare blocks in that they can be passed a list of parameters to process. This list appears inside subroutines as the special variable @_, from which the list of passed parameters (also known as arguments) can be extracted.

    Because the passed parameters take the form of a list, any subroutine can automatically read in an arbitrary number of values, but conversely the same flattening problem that affects lists that are placed inside other lists also affects the parameters fed to subroutines.

    The flexibility of the parameter passing mechanism can also cause problems if we want to actually define the type and quantity of parameters that a subroutine will accept. Perl allows us to define this with an optional prototype, which, if present, allows Perl to do compile-time syntax checking on how our subroutines are called.

    Subroutines, like bare blocks, may return either a scalar or a list value to the calling context. This allows them to be used in expressions just as any other Perl value is. The way this value is used depends on the context in which the subroutine is called.

    Declaring and Calling Subroutines

    Subroutines are declared with the sub keyword. When Perl encounters sub in a program it stops executing statements directly, and instead creates a subroutine definition that can then be used elsewhere. The simplest form of subroutine definition is the explicit named subroutine:
    sub mysubroutine {
    print "Hello subroutine! \n";
    }
    

    We can call this subroutine from Perl with:

    # call a subroutine anywhere
    mysubroutine ();
    

    In this case we are calling the subroutine without passing any values to it, so the parentheses are empty. To pass in values we supply a list to the subroutine. Note how the subroutine parentheses resemble a list constructor:

    # call a subroutine with parameters
    mysubroutine ("testing", 1, 2, 3);
    

    Of course just because we are passing values into the subroutine does not mean that the subroutine will use them. In this case the subroutine entirely ignores anything we pass to it. We'll cover passing values in more detail shortly.

    In Perl it does not matter if we define the subroutine before or after it is used. It is not necessary to predeclare subroutines. When Perl encounters a subroutine call it does not recognize, it searches all the source files that have been included in the program for a suitable definition, and then executes it. However, defining or predeclaring the subroutine first allows us to omit the parentheses and use the subroutine as if it were a list operator:

    # call a previously defined subroutine without parentheses
    mysubroutine;
    mysubroutine "testing", 1, 2, 3;
    

    Note that calling subroutines without parentheses alters the precedence rules that control how their arguments are evaluated, which can cause problems, especially if we try to use a parenthesized expression as the first argument. If in doubt, use parentheses.

    We can also use the old-style & code prefix to call a subroutine. In modern versions of Perl (that is, anything from Perl 5 onwards) this is strictly optional, but older Perl programs may contain statements like:

    # call a Perl subroutine using the old syntax
    &mysubroutine;
    &mysubroutine();
    

    The ampersand has the property of causing Perl to ignore any previous definitions or declarations for the purposes of syntax, so parentheses are mandatory if we wish to pass in parameters. It also has the effect of ignoring the prototype of a subroutine, if one has been defined. Without parentheses, the ampersand also has the unusual property of providing the subroutine with the same @_ array that the calling subroutine received, rather than creating a new one. In general, the ampersand is optional and, in these modern and enlightened times, it is usually omitted for simple subroutine calls.

    Anonymous Subroutines and Subroutine References

    Less common than named subroutines, but just as valid, are anonymous subroutines. As their name suggests, anonymous subroutines do not have a name. Instead they are used as expressions, which return a code reference to the subroutine definition. We can store the reference in a scalar variable (or as an element of a list or a hash value) and then refer to it through the scalar:

    my $subref = sub {print "Hello anonymous subroutine";};
    

    In order to call this subroutine we use the ampersand prefix. This instructs Perl to call the subroutine whose reference this is, and return the result of the call:

    # call an anonymous subroutine
    &$subref;
    &$subref ("a parameter");
    

    This is one of the few places that an ampersand is still used. However, even here it is not required, we can also say:

    $subref->();
    $subref->("a parameter");
    

    These two variants are nearly, but not quite, identical. Firstly, &$subref; passes the current @_ array (if any) directly into the called subroutine, as we briefly mentioned earlier. Secondly, the ampersand disables any prototypes we might have defined for the subroutine. The second pair of calls retains the prototype in place. (We cover both of these points later in the chapter.)

    We can generate a subroutine reference from a named subroutine using the backslash operator:

    my $subref = &mysubroutine;
    

    This is more useful than one might think, because we can pass a subroutine reference into another subroutine as a parameter. The following simple example demonstrates a subroutine taking a subroutine reference and a list of values, and returning a new list generated from calling the subroutine on each value of the passed list in turn:

    #!/usr/bin/perl 
    # callsub.pl
    use warnings;
    use strict;
    sub do_list {
    my ($subref, @in) = @_;
    my @out;
    map {push @out, &$subref ($_)} @in;
    return @out;
    }
    sub add_one {
    return $_[0] + 1;
    }
    $, = ",";
    print do_list (&add_one, 1, 2, 3);   #prints 2, 3, 4
    

    Some Perl functions (notably sort), also accept an anonymous subroutine reference as an argument. We do not supply an ampersand in this case because sort wants the code reference, not the result of calling it. Here is a sort program that demonstrates the different ways we can supply sort with a subroutine. The anonymous subroutine appearing last will not work with Perl 5.005:

    #!/usr/bin/perl 
    # sortsub.pl
    use warnings;
    use strict;
    # a list to sort
    my @list = (3, 4, 2, 5, 6, 9, 1);
    # directly with a block
    print sort {$a cmp $b} @list;
    # with a named subroutine
    sub sortsub {
    return $a cmp $b;
    }
    print sort sortsub @list;
    # with an anonymous subroutine
    my $sortsubref = sub {return $a cmp $b;};
    print sort $sortsubref @list;
    

    Of course, since we can get a code reference for an existing subroutine we could also have said:

    $sortsubref = &sortsub;
    

    The advantage of using the anonymous subroutine is that we can change the subroutine that sort uses elsewhere in the program, for example:

    # define anonymous subroutines for different sort types:
    $numericsort = sub {$a <=> $b};
    $stringsort = sub {$a cmp $b };
    $reversenumericsort = sub {$b <=> $a};
    # now select a sort method
    $sortsubref = $numericsort;
    

    The disadvantage of this technique is that unless we take care to write and express our code clearly, it can be very confusing to work out what is going on, since without running the code it may not always be possible to tell which subroutine is being executed where. We can use print $subref to print out the address of the anonymous subroutine, but this is not nearly as nice to read as a subroutine name.

    It is also possible to turn an anonymous subroutine into a named one, by assigning it to a typeglob. This works by manipulating the symbol table to invent a named code reference that Perl thereafter sees as a subroutine definition. This leads to the possibility of determining the actual code supported by a subroutine name at run-time, which is handy for implementing things like state-machines. This will be covered more fully in 'Manipulating the Symbol Table Directly' in Chapter 8.

    Strict Subroutines and the 'use strict subs' Pragma

    The strict pragma has three components, refs, vars, and subs. The subs component affects how Perl interprets unqualified (that is, not quoted or otherwise identified by the syntax) words or 'barewords' when it encounters them in the code.

    Without strict subroutines in effect, Perl will allow a bareword and will interpret it as if it were in single quotes:

    $a = bareword;
    print $a;   #prints "bareword";
    

    The problem with this code is that we might later add a subroutine called bareword, at which point the above code suddenly turns into a function call. Indeed, if we have warnings enabled, we will get a warning to that effect:

    Unquoted string "bareword" may clash with future reserved word at ...
    

    Strict subroutines are intended to prevent us from using barewords in a context where they are ambiguous and could be confused with subroutines. To enable them, use one of the following:

    use strict;    # enables strict refs, vars, and subs
    use strict subs;   # enables strict subs only
    

    Now any attempt to use a bareword will cause Perl to generate a fatal error:

    Bareword "bareword" not allowed while "strict subs" in use at ...
    

    Ironically, the second example contains the illegal bareword subs. It works because at the point Perl parses the pragma it is not yet in effect. Immediately afterwards, barewords are not permitted, so to switch off strict subs again we would have to use either quotes or a quoting operator like qw:

    no strict 'subs';
    no strict q(subs);
    no strict qw(subs);
    

    Predeclaring Subroutines

    Perl allows subroutines to be called in two alternate syntaxes; functions with parentheses or list operators. This allows subroutines to be used as if they were one of Perl's built-in list operator functions such as print or read (neither of which require parentheses).

    This syntax is only valid if Perl has already either seen the subroutine definition or a declaration of the subroutine. The following subroutine call is not legal, because the subroutine has not yet been defined:

    debug "This is a debug message";   # ERROR: no parentheses 
    #...rest of program...
    sub debug {
    print STDERR @_, "\n";
    }
    

    The intention here is to create a special debug statement, which works just like the print statement, but prints to standard error rather than standard out, and automatically adds a linefeed. Because we want it to work like print in all other respects we would prefer to omit the brackets if we choose to, since print allows us to do that.

    # predeclare subroutine 'debug'
    sub debug;
    debug "This is a debug message";   # no error
    #...rest of program...
    sub debug {
    print STDERR @_, "\n";
    }
    

    Subroutines are also predeclared if we import them from another package (see Chapter 10 for more on packages), as in:

    use mypackage qw(mysubroutine);
    

    It is worth noting here that even if a package automatically exports a subroutine when it is used, that does not predeclare the subroutine itself. In order for the subroutine to be predeclared, we must name it in the use statement. Keeping this in mind, we might prefer just to stick to parentheses.

    Overriding Built-in Functions

    Another way to predeclare subroutines is with the use subs pragma. This not only predeclares the subroutine, but also allows us to override Perl's existing built-in functions and replace them with our own. We can access the original built-in function with the CORE:: prefix. For example, here is a replacement version of the srand function, covered in Chapter 34, which issues a warning if we use srand in a version of Perl of 5.004 or greater without arguments:

    #!/usr/bin/perl
    # srandcall.pl
    use warnings;
    use strict;
    use subs qw(srand);
    sub srand {
    if ($] >= 5.004 and not @_) {
    warn "Unqualified call to srand redundant in Perl $]";
    } else {
    # call the real srand via the CORE package
    CORE::srand @_;
    }
    }
    

    Now if we use srand without an argument and the version of Perl is 5.004 or greater, we get a warning. If we supply an argument we're assumed to know what we are doing and are supplying a suitably random value.

    Subroutines like this are generally useful in more than one program, so we might want to put this definition into a separate module and use it whenever we want to override the default srand:

    #!/usr/bin/perl
    # mysrand.pm
    package mysrand;
    use strict;
    use vars qw(@ISA @EXPORT @EXPORT_OK);
    use Exporter;
    @ISA = qw(Exporter);
    @EXPORT = qw(mysrand);
    @EXPORT_OK = qw(srand);
    sub mysrand {
    if ($] >= 5.004 and not @_) {
    warn "Unqualified call to srand redundant in Perl $]";
    } else {
    # call the real srand via the CORE package
    CORE::srand @_;
    }
    }
    use subs qw(srand);
    sub srand {&mysrand;};   # pass @_ directly to mysrand
    

    This module, which we would keep in a file called mysrand.pm to match the package name, exports the function mysrand automatically, and the overriding srand function only if we ask for it.

    use mysrand;   # import 'mysrand'
    use mysrand qw(mysrand);   # import and predeclare mysrand;
    use mysrand qw(srand);   # override 'srand'
    

    We'll talk about packages, modules, and exporting subroutines in Chapter 10.

    The Subroutine Stack

    Whenever Perl calls a subroutine, it pushes the details of the subroutine call onto an internal stack. This holds the context of each subroutine, including the parameters that were passed to it in the form of the @_ array, ready to be restored when the call to the next subroutine returns. The number of subroutine calls that the program is currently in is known as the 'depth' of the stack. Calling subroutines are higher in the stack, and called subroutines are lower.

    This might seem academic, and to a large extent it is, but Perl allows us to access the calling stack ourselves with the caller function. At any given point we are at the 'bottom' of the stack, and can look 'up' to see the contexts stored on the stack by our caller, its caller, and so on, all the way back to the top of the program. This can be handy for all kinds of reasons, but most especially for debugging.

    In a purely scalar context, caller returns the name of the package from which the subroutine was called, and undef if there was no caller. Note that this does not require that the call came from inside another subroutine - it could just as easily be from the main program. In a list context, caller returns the package name, the source file, the line number from which we were called, and the name of the subroutine that was called (i.e. us). This allows us to write error traps in subroutines like:

    sub mysub {
    ($pkg, $file, $line) = caller;
    die "Called with no parameters at $file line $line" unless @_; 
    }
    

    If we pass a numeric argument to caller, it looks back up the stack the requested number of levels, and returns a longer list of information. This level can of course be '0', so to get everything that Perl knows about the circumstances surrounding the call to our subroutine we can write:

    @caller_info = caller 0;   # or caller(0), if we prefer
    

    This returns a whole slew of items into the list, which may or may not be defined depending on the circumstances. They are, in order:

    • package: the package of the caller.
    • filename: the source file of the caller.
    • line: the line number in the source file.
    • subroutine: the subroutine that was called (that is, us). If we execute code inside an eval statement then this is set to eval.
    • hasargs: this is true if parameters were passed (@_ was defined).
    • wantarray: the value of wantarray inside the caller, see 'Returning Values' later in the chapter.
    • evaltext: the text inside the eval that caused the subroutine to be called, if the subroutine was called by eval.
    • is_require: true if a require or use caused the eval.
    • hints: compilation details, internal use only.
    • bitmask: compilation details, internal use only.

    In practice, only the first four items: package, filename, line, and subroutine are of any use to us, which is why they are the only ones returned when we use caller with no arguments. Unfortunately we do not get the name of the calling subroutine this way, so we have to extract that from further up the stack:

    # get the name of the calling subroutine, if there was one
    $callingsub = (caller 1)[3];
    

    Or, more legibly:

    ($pkg, $file, $line, $callingsub) = caller 1;
    

    Armed with this information, we can create more informative error messages that report errors with respect to the caller. For example:

     
    # die with a better error message
    sub mysub {
    ($pkg, $file, $line) = caller;
    die "Called from ", (caller(1)) [3], 
    " with no parameters at $file line $line \n" unless    @_;
    ...
    }
    

    If debugging is our primary interest, a better solution than all the above is to use the Carp module. The Carp module and other debugging aids are covered in Chapter 17.

    One final point about the calling stack: if we try to access the stack above the immediate caller we may not always get the right information back. This is because Perl can optimize the stack under some circumstances, removing intermediate levels. The result of this is that caller is not always as consistent as we might expect, so a little caution should be applied to its use.

    Recursion

    Recursion happens when a subroutine calls itself, either directly, or indirectly, via another subroutine (also known as mutual recursion). For example, consider this subroutine that calculates the Fibonacci sequence up to a specified number of terms:

    #!/usr/bin/perl 
    # fib1.pl
    use warnings;
    use strict;
    sub fibonacci1 {
    my ($count, $aref) = @_;
    unless ($aref) {
    # first call - initialize
    $aref = [1,1];
    $count -= scalar(@{$aref});
    }
    $aref = [1,1] unless $aref;
    if ($count--) {
    my $next = $aref->[-1] + $aref->[-2];
    push @{$aref}, $next;
    return fibonacci1($count, $aref);
    } else {
    return wantarray?@{$aref}: $aref->[-1];
    }
    }
    # calculate 10th element of standard Fibonacci sequence
    print scalar(fibonacci1(10)), "\n";
    # calculate 10th element beyond sequence starting 2, 4
    print scalar(fibonacci1(10, [2, 4])), "\n";
    # return first ten elements of standard Fibonacci sequence
    my @sequence = fibonacci1(10);
    print "Sequence: @sequence \n";
    

    Each time the subroutine is entered, it calculates one term, decrements the counter by one and calls itself to calculate the next term. The subroutine takes two arguments, the counter, and a reference to the list of terms being calculated. (As a convenience, if we don't pass in a reference the subroutine initializes itself with the start of the standard Fibonacci sequence, 1, 1). We pass in a reference to avoid copying the list repeatedly, which is wasteful. When the counter reaches zero, the subroutine exits without calling itself again, and returns either the whole list or the last term, depending on how it was called.

    This is an example of forward recursion, where we start at the beginning of the task and work our way towards the end. Elements are calculated one by one as we continue with our recursion. An alternative way of doing the same job is to use reverse recursion, which starts by trying to calculate the last term first:

    #!/usr/bin/perl 
    # fib2.pl
    use warnings;
    use strict;
    sub fibonacci2 {
    my ($count, $internal) = @_;
    if ($count <= 2) {
    # we know the answer already
    return $internal?[1,1]: 1;
    } else {
    # call ourselves to determine previous two elements
    my $result = fibonacci2($count -1, 'internal');
    # now we can calculate our element
    my $next = $result->[-1] + $result->[-2];
    if ($internal) {
    push @{$result}, $next;
    return $result;
    } else {
    return $next;
    }     
    }
    }               
    foreach (1..20) { 
    print "Element $_ is ", fibonacci2($_), "\n";
    }
    

    This time the subroutine starts by trying to work out the last term, starting at the end, and reversing back towards the beginning until we can determine the answer without a further call. If the requested term is the first or second, we just return the result, otherwise, it needs to work out the terms prior to the one we have been asked for, which it does by calling itself for the previous terms. In this model, we descend rapidly to the bottom of the recursion stack until we get the answer '[1,1]'. We then calculate each new term as we return back up.

    Reverse recursion is not as obvious as forward recursion, but can be a much more powerful tool, especially in algorithms where we do not know in advance exactly how the initial known results will be found. Problems like the Queen's Dilemma (placing eight queens on a chessboard such that no Queen can take another) are more easily solved with reverse recursion, for example.

    Both approaches suffer from the problem that Perl generates a potentially large call stack. If we try to calculate a sufficiently large sequence then Perl will run out of room to store this stack and will fail with an error message:

    Deep recursion on subroutine "main::fibonacci2" at ...
    

    Some languages support 'tail' recursion, an optimization of forward recursive subroutines where no code exists after the recursive subroutine call. Because there is no more work to do at the intermediate levels of the subroutine stack, they can be removed. This allows the final call to the recursed subroutine call to directly return to the original caller. Since no stack is maintained, no room is needed to store it.

    Perl's interpreter is not yet smart enough to figure out this optimization automatically, but we can code it explicitly using a goto statement. The fibonnaci1 subroutine we showed first is a recursive subroutine that fits the criteria for 'tau' recursion, as it returns. Here is a modified version, fibonacci3 that uses goto to avoid creating a stack of recursed subroutine calls. Note that the goto statement and the line immediately before it are the only difference between this subroutine and fibonacci1:

    #!/usr/bin/perl 
    # fib3.pl
    use warnings;
    use strict;
    sub fibonacci3 {
    my ($count, $aref) = @_;
    unless ($aref) {
    # first call - initialize
    $aref = [1,1];
    $count -= scalar(@{$aref});
    }
    if ($count--) {
    my $next = $aref->[-1] + $aref->[-2];
    push @{$aref}, $next;
    @_ = ($count, $aref);
    goto &fibonacci3;
    } else {
    return wantarray?@{$aref}:$aref->[-1];
    }
    }
    # calculate 1000th element of standard Fibonacci sequence
    print scalar(fibonacci3(1000)), "\n";
    

    The goto statement jumps directly to another subroutine without actually calling it (which creates a new stack frame). The automatic creation of a localized @_ does not therefore happen. Instead, the context of the current subroutine call is used, including the current @_. In order to 'pass' arguments we therefore have to predefine @_ before we call goto. Examining the code above, we can see that although it would sacrifice legibility, we could also replace $count with $_[0] to set up @_ correctly without redefining it.

    Recursion is a nice programming trick, but it is easy to get carried away with it. Any calculation that uses recursion can also be written using ordinary iteration too, so use recursion only when it presents the most elegant solution to a programming problem.

    Checking for Subroutines and Defining Subroutines On-the-fly

    We can check for the existence of a subroutine before we call it using Perl's defined function:

    if (defined &capitalize) {
    capitalize(@countries);
    }
    

    This is more useful than it might seem. For instance, when using a library that may or may not support a particular subroutine (depending on the installed version) we can safeguard against a possible exit from our program by checking that the library has the function before we try to call it.

    If we are writing object-oriented Perl, we can use the special object method can (supplied by the UNIVERSAL object - that's a subject for Chapter 18 though), in order to do the same thing in a more object-oriented style:

    $bean->jump('left') if $bean->can('jump');
    

    We are not limited to just testing for the existence of subroutines. We can also substitute for them and even define them on-the-fly by defining an AUTOLOAD subroutine. If an AUTOLOAD subroutine exists in the same package as a non-existent subroutine, Perl will call it, rather than exiting with an error. The name of the missing subroutine, complete with package name, is placed in the special package variable $AUTOLOAD, and the arguments passed to the subroutine are instead passed to AUTOLOAD. As a trivial example, the following AUTOLOAD subroutine just returns the missing subroutine name as a string:

    sub AUTOLOAD {
    our $AUTOLOAD;   # or 'use vars' for Perl < 5.6
    return $AUTOLOAD;
    }
    

    Because $AUTOLOAD is a package variable which we have not declared, we need to gain access to it with the our directive if use strict is in effect (Perl versions before 5.6 need to have use vars instead). The example above allows us to write strange looking statements like this:

    $, = " ";
    print "", Hello, Autoloading, World;
    

    This is identical in effect to:

    print "main::Hello", "main::Autoloading", "main::World";
    

    In other words, this AUTOLOAD subroutine interprets unqualified barewords as strings. A slightly more useful example of the same technique is shown by this HTML tag generator, which automatically creates matching start and end tags, with any supplied parameters sandwiched in between. Note the regular expression to strip off the package prefix:

    sub AUTOLOAD {
    our ($AUTOLOAD);   # again, 'use vars' if Perl < 5.6
    $AUTOLOAD =~ s/^.*:://;   # strip the package name
    return "<$AUTOLOAD> \n". join("\n",@_). "</$AUTOLOAD> \n";
    }
    

    We can now write an HTML page programmatically using functions that we haven't actually defined, in a similar (and much shorter, albeit less sophisticated) way to the CGI module. Here is an example HTML document created using the above autoloader subroutine in a single line of code:

    print html(head(title("Autoloaded HTML")), body(h1("Hi There")));
    

    While functional, this example has a few deficiencies. For a start, we can invent any tag we like, including mis-spelt ones. Another problem is that it does not learn from the past, each time we call a non-existent subroutine, Perl looks for it, fails to find it, then calls AUTOLOAD. It would be more elegant to define the subroutine so that next time it is called, Perl finds it. The chances are that if we use it once, we'll use it again. To do that, we just need to create a suitable anonymous subroutine and assign it to a typeglob with the same name as the missing function, which inserts the new subroutine into the symbol table for us. Here is a modified version that does this for us:

    sub AUTOLOAD {
    our ($AUTOLOAD);
    no strict 'refs';
    my $tag = $AUTOLOAD;
    $tag =~s/.*:://;
    *$AUTOLOAD = sub {
    "<$tag> \n". join("\n", @_). "</$tag> \n";
    };
    &$AUTOLOAD;   # we can use a 'goto' here too -- see below
    }
    

    Now, whenever a tag is asked for, a subroutine for that tag is defined. The next time the same tag is asked for, the newly defined subroutine catches the call and handles it.

    Aside from the anonymous subroutine definition, the other interesting point about this autoloading subroutine is the call to the new subroutine at the end.

    Since AUTOLOAD has to define the subroutine the first time it is called, it has to call it as well. We make use of the &subname; syntax to pass the contents of @_ directly to the new subroutine. However, $AUTOLOAD is a symbolic reference, so we use no strict refs at the top of the subroutine.

    AUTOLOAD subroutines that define subroutines are one place where using goto does make sense. We can replace the last line of this subroutine with:

    goto &$AUTOLOAD;
    

    Why is this useful? Because it removes the AUTOLOAD subroutine itself from the calling stack, so caller will not see the AUTOLOAD subroutine, but rather the original caller. So goto is consequently a common sight in AUTOLOAD subroutines that define subroutines on-the-fly.

    Autoloading is quite handy in functional programming, but much more useful in modules and packages. Accordingly we cover it in more depth in Chapter 10.


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

    More Web Development Articles
    More By Developer Shed

       

    WEB DEVELOPMENT ARTICLES

    - On Page SEO for New Domains
    - Improve Your Site`s Speed
    - Safari Books Online Review
    - Creating an Estore From the Ground Up
    - Most Common SEO Mistakes Developers Make
    - Making the Most of Your Titles and Meta Desc...
    - Five Ways Using Flash Can Damage Your Site
    - A Web Designer`s Guide to Colors
    - Use Webstarts to Create a Free Site
    - More Than Just Looks. How Your Web Design C...
    - How to Design Content Pages
    - Mint Review
    - Make Your WordPress Website Look Professional
    - How to Create a Mobile Web Site
    - Meta Tags: Still Useful?

    Developer Shed Affiliates

     



    © 2003-2018 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap