Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Placement of Subs

by venimfrogtongue (Novice)
on Mar 25, 2002 at 08:12 UTC ( [id://154044]=perlquestion: print w/replies, xml ) Need Help??

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

I read in my llama book that subs can be either on top or bottom of the script and still run as expected. But I have heard here and other places online that it is better to place it on top. Then I also hear it is better on bottom. Is there any real better position for subs? Thanks! <1-- Changed title from "Subs" (turnstep) -->

Replies are listed 'Best First'.
Re: Subs
by gmax (Abbot) on Mar 25, 2002 at 08:58 UTC
    Mostly, it's a problem of style. If you know what you are doing, it doesn't really matter. There are some pitfalls that you should be aware of, though.
    Consider the following case, with subs on bottom, and calls to the subs on top. You see that there is a variable $stuff, declared before the sub. So you think it shouldn't be a problem to call your sub, which should print "ABCD". Unfortunately, it doesn't work like that. Your variable doesn't get initialized, because the program flow hasn't reached that point yet.
    #!/usr/bin/perl -w use strict; dosomething(); my $stuff = "ABCD"; # bottom sub sub dosomething { print "$stuff\n"; }
    OTOH, if you put your call to the sub at the end of the file, transforming your sub into a "top" sub, then you face the problem of unintended globals that Juerd is referring to. In the following case, your "dosomething" will work as expected, unless you call "dosomethingelse" first, in which case your lexical variable gets changed.
    Using globals (including unintended ones) in this way is not recommended. If you really must have them, consider either creating a package or using closures.
    #!/usr/bin/perl -w use strict; my $stuff = "ABCD"; # visible to all subs from now on #top subs { # start closure my $privatestuff = "WOW!"; #visible only from dosomething sub dosomething { print "$stuff \t $privatestuff\n"; } } # end closure sub dosomethingelse { $stuff = "WXYZ"; } dosomething();
    Most of the problems that you might have with subs are related to using globals (or lexically scoped that act like globals) or not.
    If your subs use parameters instead of globals, there are no such side effects when you call them, no matter where they are declared. The only difference will be that you have to use parentheses when you call subs that have not been defined yet.
    #!/usr/bin/perl -w use strict; dosomething("ABCD"); #top subs sub dosomething { my $arg = shift; print "$arg\n"; } dosomething "EFGH";
    My personal recommendation is: if you have a lot of subs, consider making a module out of them.
    HTH
     _  _ _  _  
    (_|| | |(_|><
     _|   
    
Re: Subs
by Juerd (Abbot) on Mar 25, 2002 at 08:19 UTC

    But I have heard here and other places online that it is better to place it on top.

    It is. Placing them at the top avoids sharing of ALL lexically scobed variables in the file scope ("unintended globals"). It also allows you to not write parens (which isn't really a problem if you like parens anyway).

    Have a look at this recent meditation: where do you put your subs.

    Especially demerphq's posts. (and mine of course *grin*)

    U28geW91IGNhbiBhbGwgcm90MTMgY
    W5kIHBhY2soKS4gQnV0IGRvIHlvdS
    ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
    geW91IHNlZSBpdD8gIC0tIEp1ZXJk
    

      Thanks millions for all your help, everyone! One thing I have noticed, seeming this is my first attempt to learn any programming language, is there is never just one way to do things. Everyone has their own way to set things up, kinda gets confusing as a newbie when one person tells you to do this while others say now :) Gotta love perl though, too addicting. Thanks everyone!
Re: Subs
by shotgunefx (Parson) on Mar 25, 2002 at 10:20 UTC
    Unless one of the reasons above, I put my subs at the bottom. Lexical scoped variables that should be visible throughout at the top of the file. If I want to hide anything, I'll put the lexically scoped variables and the subs for them in their own enclosing block. The way I code, "unintended" globals are not a problem. I always use my on everything in a sub, unless... the referenced variable is supposed to be visible to the sub from outside. In general, globals usually are bad but some people would make it out to be a most vile offense. Like most things, they have their place.

    -Lee

    "To be civilized is to deny one's nature."
Re: Subs (Placement when Prototyping)
by Jazz (Curate) on Mar 25, 2002 at 18:55 UTC

    On a side note...

    If you use prototypes and the sub appears on the bottom (or after the invocation), the prototype will not work as intended. You'll get a "main::subroutine called too early to check prototype" warning and the prototype will not/cannot be checked. When using prototypes, you'll need to either place the sub before its invocation or declare the sub and its prototype:

    sub prototest($); # declare sub and prototype prototest( 4 ); # dies if no param or more than 1 param is passed sub prototest($){ print '1, 2, 3, ', @_; }
    -or-
    sub prototest($){ print '1, 2, 3, ', @_; } prototest( 4 ); # dies if no param or more than 1 param is passed

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://154044]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-03-28 13:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found