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

I'm working on a little program that uses subs, but I'm having difficulty wrapping my brain around how to make local variables in subs and then pass the values contained in the subs out to main. The text book for this class (which I'm not wholly impressed with) says that, since all variables in Perl are global (unless otherwise specified) just call the variable from outside the sub.

But I don't want to do that, because then I have variables stepping all over each other and it's just a damned mess.

So, my questions are:

1) Is this were "my" comes in? What about "local?" What's the difference? I understand local went out with the goto statement. True?

2) How do I return a value from a sub to main, if Perl doesn't have a return statement?

If there's a tutorial I'm missing (I looked, but they all seem very advanced compared to what I'm doing) just point me to it and I'll go look

Thanks!

Bryan

Replies are listed 'Best First'.
Re: Several stupid questions about subs
by fidesachates (Monk) on Apr 13, 2011 at 16:17 UTC
    Perl does have a return statement. You can return the variables.
    use strict; use warnings; my $test = foo(); print $test."\n"; sub foo { return "Hello World!"; }


    Your question regarding my and local deals with variable scoping. I could explain here, but here is a link that does it quite well. http://perl.plover.com/FAQs/Namespaces.html

    For the record, my isn't the answer here. My creates a variable that exists only within the scope it was created in. If you create it in a sub, it lasts only inside that sub. If you create it in the main part of the script, it'll last throughout the file including the subs.

    local is a tricky subject. There are monks with better knowledge of it than me, but the basics are that it creates a localized version of a global sub it takes a global variable, stores the value somewhere safe, gives it a new value. That value is then used until the end of the control block where the original value is give back to the variable. It was created before my and most perl programmers do not use it anymore.
Re: Several stupid questions about subs
by ikegami (Patriarch) on Apr 13, 2011 at 16:19 UTC

    1) Is this were "my" comes in? What about "local?" What's the difference? I understand local went out with the goto statement. True?

    To explain the differences, there would have to similarities.

    my creates a lexically scoped variable.

    local temporarily saves a package variable, array element or hash element. The previous value of the variable will be restored when the current scope is exited.

    2) How do I return a value from a sub to main, if Perl doesn't have a return statement?

    By using the return statement or by evaluating the value to return as the last statement of the sub.

    sub f { ...; return $x + 1 } sub f { ...; $x + 1 }
Re: Several stupid questions about subs
by luis.roca (Deacon) on Apr 13, 2011 at 16:23 UTC

    Why not show some of the code you've done so far? Don't worry about it if you think it's really bad — that's why you came here right? :)

      From the perldocs:
    • perlintro - scroll down to the section 'Perl Variable Types'

    You've been given some good answers already but it's not a bad idea to get more familiar with the site's tutorials and the perldocs.


    "...the adversities born of well-placed thoughts should be considered mercies rather than misfortunes." — Don Quixote
Re: Several stupid questions about subs
by mikeraz (Friar) on Apr 13, 2011 at 16:18 UTC

    1) yes, this is where my* comes in.
    2) you could read the perlsub man page and search for the word return and be pleased to know that perl subs return a value. You get to choose which one.
    The perlsub page really is a good starting point.

    Edit * for the scope of your question and the assumed use case. See other response for helpful scoping tutorials.


    Be Appropriate && Follow Your Curiosity
Re: Several stupid questions about subs
by GrandFather (Saint) on Apr 14, 2011 at 05:54 UTC

    You are right to be unimpressed with your text book! "Modern" Perl provides very good management of variable locality and you almost never need to use global variables. There are very good reasons for not using globalvariables if they can be avoided. Related to this is the mantra: always use strictures (use strict; use warnings;), which helps avoid some of the worst aspects of old school Perl variables ("package" variables) by forcing you to use "lexical" variables. That doesn't prevent you introducing global lexical variables however, that is something you have to dicipline yourself against.

    local provides a way of reusing a (generally) package variable in a local (runtime) scope. my creates a new instance of a variable in a lexical scope (generally up to the enclosing } or end of the file). local still has valid uses, but unless you need local's special proerties, my is what you should go for.

    True laziness is hard work
Re: Several stupid questions about subs
by choroba (Cardinal) on Apr 13, 2011 at 16:15 UTC
Re: Several stupid questions about subs
by tospo (Hermit) on Apr 14, 2011 at 07:27 UTC
    Which text book is this? Where are you doing your course? It clearly isn't very good. I once observed an online training course for biologists to learn some basic Perl in which some of my colleagues took part. The guy who did it said that he advises against all that "strict, warnings and 'my'" stuff because he gets annoyed by all those error messages. Then he got himself into big trouble with a typo in a variable name which of course would have been caught by all those "annoying messages"! Took him ages to find the problem....
    In short (and as already mentioned here): use strict (and warnings) and keep your variables scoped with 'my'. A good subroutine should have a clear input and output and have as few hidden side-effects as possible. Then it is clear to anybody what it does and it is easy to maintain the code. To achieve that you explicitly pass it the input variables, then access them with local variables as shown above ( something like my ($var1,$var2) = @_;) and then return one or more values explicitly. Sometimes a sub doesn't have an obvious return value and in that case you often return "1" or "0" to indicate success or failure of whatever the sub did.
    Using global variables and making some changes to them somewhere in the sub means that it is not clear at all what it does and the hole point of making the sub (put some code in a blackbox), is lost.
Re: Several stupid questions about subs
by JavaFan (Canon) on Apr 13, 2011 at 16:37 UTC
    I understand local went out with the goto statement. True?
    That is true. But true in the sense that both local and goto are still part of the language, and still actively used. Many people will tell you they never use goto, but then use next, last, and redo happily - which are just glorified gotos.
Re: Several stupid questions about subs
by Anonymous Monk on Apr 13, 2011 at 18:38 UTC
    1) local was an old implementation for trying to scope variables, not in favor anymore (can cause unexpected behavior if you pass through nested subroutine calls due to the way it temporarily replaces variable)

    2) use my to scope all variables; limit scope to smallest practical enclosing block

    3)

    use strict; use warnings;
    in all scripts

    4) Get a copy of "The Camel" (Programming Perl, 3e); if you're completely new to programming you may find Learning Perl helpful too.

    5) There is a return statement, see references in #4

    -Greg

Re: Several stupid questions about subs
by simonodell (Acolyte) on Apr 13, 2011 at 17:15 UTC
    Personally I never use local and as far as I am aware you shouldn't either! Perl does have a return statement!
    my $var = foo(); sub foo { return 'bar'; } print $var;
    what you get printed out is the word 'bar'. if you want to pass variables to a sub there are various ways;
    my $var = foo('some_text_for_instance'); sub foo { my $text = $_[0]; return 'bar'; }
    As far as I understand it $_[0], represents the first element of an array sent to the sub... so if you can do stuff like this;
    my $var = foo($somevar,"some text",$somehashref); sub foo { my $variable = $_[0]; my $text = $_[1]; my $hashref = $_[2]; return $hashref->{'some_key'}; }
    You can also capture the whole passed array;
    sub foo { my @private_local_array = @_; #then lets return element 5 for some reason return $private_local_array[4]; }
    There is also my $var = shift; but I'm not sure what that is or does or why one would want to use it.
      my @digitsOfPi = (3,1,4,1,5,9,2,6,5,3,5,9,'etc'); frobnicate('foo', 'bar', @digitsOfPi); sub frobnicate { my $fooString = shift; my $barString = shift @_; #more typing my @remainder = @_; print $remainder[0] == 3 ? 'yum' :'eew'; }

        my (...) = @_; is a very common way of getting args. I can't believe it wasn't mentioned.

        sub frobnicate { my ($foo, $bar, @remainder) = @_; print $remainder[0] == 3 ? 'yum' :'eew'; }
Re: Several stupid questions about subs
by tchrist (Pilgrim) on Apr 14, 2011 at 18:56 UTC
    I understand local went out with the goto statement. True?
    Certainly false. Just yesterday I wrote:
    local $Opt{debug} = 1; some_function();

    It is in just such sitations that local shines. Here’s another:

    local $SIG{INT} = "IGNORE";

    And another:

    @paragraphs = do { local $/ = q(); <FH> };
    Despite the general usefulness of compile-time scoping, there are still times when you want run-time scoping. For example, exception blocks are run-time scoped.
Re: Several stupid questions about subs
by locked_user sundialsvc4 (Abbot) on Apr 13, 2011 at 17:56 UTC

    This is one of my favorite reasons for using Perl “objects.”   The standard way of doing this in Perl might not conform to anyone’s college textbook, but it nevertheless is quite practical.   An object is basically “a blessed hash,” and as such it contains both code and data in one convenient, self-ecapsulated “thing.”   Each instance of an object neatly stands by itself, with easy access to “its” data.   Variables declared within the package are naturally shielded from anyone outside.   And so on.   It is a pragmatic solution to issues kind-of like the ones you are considering now ... and never mind your college textbook, anyway.

      How are mentioning advanced topics like 'bless' and 'package' in a thread where the OP is not even familiar with some of the basic concepts of Perl helpful? Or pragmatic for that matter? I admire your enthusiasm to help, but please think about the knowledge level of the people you are trying to help when posting!

      Elda Taluta; Sarks Sark; Ark Arks

        /me nods...

        I certainly do not mean to “shoot over the head of” anyone, let alone purposefully.   But even if every technical detail of what I outlined (inadvertantly...) is too esoteric, I hope that the essential notion is both useful and clear, and relevant.

Re: Several stupid questions about subs
by anonymized user 468275 (Curate) on Apr 19, 2011 at 15:34 UTC
    my creates dynamic allocation for the variable within the current scope only. So for example, if you have a bunch of subroutines all having my %parm = @_ at the beginning, then after calling each other, even recursively, the values in %parm remain distinct and preserved across all such calls and returns.

    local, as has been said, makes special use of a global or package variable. Whereas it may be unusual to use it for ordinary variables, given that my is sufficient for this purpose, it comes into its own for built-in variables. For example, if a subroutine uses $_, it can ensure preservation of the callers value for $_, simply by declaring local $_, whereas my $_ just won't be allowed, even without the strict or warning pragmas. So local is absolutely necessary for this and is almost a sine qua non if one wants to use $_ in a module method without "hurting" any possible caller.

    The argument about goto was best explained by Kathleen Jensen in the 1970s in the definitive Pascal book known to most as "Jensen and Wirth". The arguments therein apply to Perl as much as any "block structured" language, that is to say, whereas block structure might technically obviate the need for goto, it remains justified and even encouraged (by me at least) for the special case of breaking out of structure on encountering an exception. For example:-

    sub fred { my $self = shift; $self -> parse or goto SORRYFRED; while ( $self -> codegen ) { $self -> codeprint or goto SORRYFRED; } return 1; SORRYFRED: print STDERR $self -> formatmsg; $self -> { SEVERITY } < 2 or $self -> cexit; # case of fatal 0; # case of warning }
    If an exception occurs in a while loop, or worse a nested while loop, why punish yourself and your code by messing with the loop conditions and artificially adding huge if blocks and so on? It must be more readable and maintainable to jump out to an error handler at a higher scope like in above sketched example.

    Finally, if you don't want to return explicitly, the value of the statement of the routine will get returned to the caller anyway, so in the above example, there are two explicit returns (update: actually I mean an explicit return and a call to an exit routine to manage exit codes for example) and the final way out at the last line is just a 0; to return 0 to the caller.

    One world, one people