mat21 has asked for the wisdom of the Perl Monks concerning the following question:

Hi everybody,

I am trying to improve my understanding of the perl language because I would like to implement some packages as well as possible.
I saw that some pecularities of perl are often used. I understood how they work but I would like to understand when it is really useful to use them (or when we should use them):

1/ BEGIN/END
(in which case it is usefull to initialize variables before compiling all?)

2/ typeglob
(what is the avantage tu use *a instead of $a + @a + %a for exemple.)

3/ sub AUTOLOAD

I know this question is quite large but if you could just tell me when you use these elements that will be great.

Thanks.

Replies are listed 'Best First'.
Re: which use for any Perl elements?
by dragonchild (Archbishop) on Dec 03, 2004 at 15:06 UTC
    In almost every case, if you don't know why you should use it, you probably shouldn't be using it. I know this sounds glib, but it's really the truth.
    1. BEGIN/END ... use these when you ABSOLUTELY HAVE TO have something occur before literally anything else or after literally everything else. In 10 years, I have used BEGIN and END maybe 10 times. I have used INIT once and I have never used CHECK. In practice, most Perl programmers will never use these phase things. Ever.

      The only exception to that is I will often put this in certain scripts:

      my $dbh = DBI->connect( ... ) or die $DBI::errstr; END { $dbh->disconnect if $dbh }
    2. globs ... In Perl4, they were the only ways to create multi-dimensional data structures. Now, we have references. Also, in early Perl5s, they were the only ways to pass filehandles to subroutines. Now, we have lexical filehandles.

      Now, the only thing I use them for is to create subroutines on the fly, and I do this quite a bit. Something like *foo = sub { print "foo\n" };. In every other case, you will use $a / @a / %a.

    3. AUTOLOAD ... This is probably the feature of Perl that is least needed and most overused. I have used AUTOLOAD exactly once in production code, and that was in the same CPAN module I used INIT. Some people love it, some people don't. I'm in the camp that says "If I need a catchall bucket, I probably didn't design right." So, using AUTOLOAD is a red flag to me saying I probably need to do more brainwork and less fingerwork.

    Does that help?

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      Something like *foo = sub { print "foo\n" };

      Sorry, I have never understood typeglobs either: why would this be preferable to my $foosub = sub { print "foo\n" };?

        $a = sub { ... }; # called: $a->(); *b = sub { ... }; # called: b();

        Ted Young

        ($$<<$$=>$$<=>$$<=$$>>$$) always returns 1. :-)
      This thread seems fairly dead, but I can't believe nobody mentioned what is probably the most frequent use of BEGIN: calling CGI::Carp qw{ fatalsToBrowser } in a BEGIN allows compile-time errors to be sent to the browser, which is an incredibly useful feature for debugging. Otherwise, compile-time errors simply generate a 500 Internal Server Error, and debugging requires digging through the the logs.
Re: which use for any Perl elements?
by TedYoung (Deacon) on Dec 03, 2004 at 15:08 UTC

    Hello,

    BEGIN blocks ensure that their contents are executed during compilation. It turns out that the "use" statement is really a shorthand for:

    BEGIN { require Foo; Foo->import(@LIST) }

    The BEGIN block should be used for initialization that needs to occur early in your program. In most cases, initializing your variables, etc, at the top of your package is just fine.

    END is a little easier to provide some examples for. END is used mostly for tear down and clean up. If you module needs to do something at the end of the program's life, an END block is a good choice. For example, this can be used to close database handles or file handles that reamin open throughout the life of your program.

    BEGIN and END are quite often used in one-liners that take advantage of perl's -n and -p options. -p effectivly wraps your code in the following:

    while (<>) { # ... your code here ... print $_; }

    (Note the -n is the same as -p without the final print statement). So, if you are writing a one-line like:

    perl -p -e "$_ = reverse $_" f1

    This would print each line in f1 reversed (eg. ABC would be printed CBA). Now, if you needed to do some initialization ahead of time, or print a summary, the BEGIN and END blocks come into play:

    print -p -e "$_ = reverse $_; $i ++; END { print qq'Total lines $i.' } +" f1

    This would print your reversed lines and then tell you how many lines were in the file afterwards.

    Typeglobs can be used to mess with the symbol table, a magical hash table that stores all global variables (not those declared with my). By far the most common use is to create an alias. An alias is a variable, that when updated also updates its source. For example:

    $a = 6; *b = \ $a; $b = 5; print $a; # prints 5 @a = (1, 2, 3); *b = \ @a; pop @b; print "@a"; # prints 1 2

    AUTOLOAD is used in a most to catch undeclared method/sub invocations in a package. For example (perhapse the most commonly sited example, let's say we wanted to make a package that gave us a bunch of shell commands as perl subs. For example:

    use Shell; $a = Shell::cat("file.text"); Shell::cp("a.txt", "b.txt");

    Well, you could impliment every single shell command as a sub that calls the appropriate shell command:

    package Shell; sub cat { `cat @_` } sub cp { `cp @_` }

    But that would be a nightmare. Instead, we can use an AUTOLOAD to trap all calls to Shell package:

    package Shell; sub AUTOLOAD { $AUTOLOAD =~ s/^.*:://; # Strip out the package name from the sub +'s name (in this case Shell::) `$AUTOLOAD @_` }

    Well, these examples are a little contrived and seriously simplified to show you where you might use them.

    I will update this reply if I can think of any better examples.

    Ted Young

    ($$<<$$=>$$<=>$$<=$$>>$$) always returns 1. :-)
      (post is a little bit irrelevant to the questions asked)

      -p (and -n) wraps your code in:

      while (<>) { # ... your code here ... } continue { print $_; }

Re: which use for any Perl elements?
by gaal (Parson) on Dec 03, 2004 at 17:43 UTC
    Another place where AUTOLOAD can be useful, apart from TedYoung's suggestion, is when you are implementing a remote invocation handler.

    The problem: you want your code to use regular funciton calls, but run on a remote machine.

    The solution: write an AUTOLOAD routine that catches each request of this type, checks it against a list of valid commands to run, sends the request and the parameters over the wire somehow to the other end, and communicates the results. (There can be many variations of this idea; a common one being to put the validation on the server side of things. This is actually better design, because a server should generally not trust just anything a client gives it.)

    On the other side, you have to actually run some function by its name. This, if you've been reading <cite>Advanced Perl Programming</cite>, is closely related to symbol table stuff, although you don't necessarily pass a typeglob around explicitly. And although you didn't ask about it, it is also an example of a good time for turninig off use strict :)

    As for END blocks, they're convenient places to place cleanup code. Delete temporaray files, close database connections... of course, if your code is simple and has one possible flow, you may not need this.

Re: which use for any Perl elements?
by Fletch (Bishop) on Dec 03, 2004 at 15:11 UTC

    Gee, why not go up to your calculus teacher and ask them "So, when is it useful to use this 'integral' thing?"

    Your questions are not just "quite large", they're almost too open ended to be practically answered. Find a good book on Perl (the Camel, the Llama) and read it all the way through. Read things like perldoc perlsub which covers all three of these topics. Then if you have specific questions you might get some reasonable responses.

      I have read several times "Advanced Perl Programming". That's why I understand how they work but it is not really defined when I have to use them.
      I sometimes saw some modules using these technics and I wanted to know if it is recommended to use them when you implement modules/packages.
      dragonfly is certainly plenty of wisdom when he says "if you don't know why you should use it, you probably shouldn't be using it."
      I didn't ask for a course but just PM to share their own experience on those things. Don't waste too much time on this question.

      thank you for your answers.