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

I have some very basic questions about use strict and subroutines. I'm just getting started so pardon my lack of understanding.
I have some code:
#!/usr/local/bin/perl use strict; myname(); print "my name is $myname\n"; sub myname { my $myname = "bill"; return $myname; }
I don't understand why this doesn't work. Where do I need to declare $myname? I thought I would have access to it at my print statement since I'm returning it in the subroutine.

I change that code a little bit in my experimenting to:

#!/usr/local/bin/perl use strict; my $myname = undef; myname(); print "my name is $myname\n"; sub myname { $myname = "bill"; return $myname; }
This prints out what I expect, but I notice that it works the same if I remove the return line from the subroutine. Why is this? Do I need to return the variable? What is the best way to go about using strict with subroutines?

Since I'm already displaying my basic lack of understanding of local/global variables, when do I need to pass variables into a subroutine? I'm currently creating variables and using them later in subroutines without passing them in and having no problems. Is this the wrong way to do it?

Thanks for any help.

Replies are listed 'Best First'.
(jeffa) Re: use strict and subroutines
by jeffa (Bishop) on Apr 02, 2001 at 19:53 UTC
    When you return a value from a subroutine, you should 'catch' it in a variable, or use it outright:
    my $myname = myname(); # or print myname(), "\n";
    A return token is really quite optional - Perl will return the last value evaluated, so:
    sub myname { my $name = "bill"; }
    will return 'bill.' As for your second example - $myname is declared outside of sub myname - but it is accessible by myname(). It works because you defined $myname, unlike you did in the first example.

    The best way to deal with this is like so:

    my $myname = myname(); print "my name is $myname\n"; sub myname { my $name = "bill"; # notice subtle change in variable name return $name; # not necessary, $myname works too } # but it is not the same $myname ;)

    Jeff

    R-R-R--R-R-R--R-R-R--R-R-R--R-R-R--
    L-L--L-L--L-L--L-L--L-L--L-L--L-L--
    
Re: use strict and subroutines
by arhuman (Vicar) on Apr 02, 2001 at 19:52 UTC
    This should solve your problem :
    #!/usr/local/bin/perl use strict; $myname=myname(); print "my name is $myname\n"; sub myname { my $myname = "bill"; return $myname; }

    Your problem is that you seem to not understand the scope of variable (the way my works)
    and the way a sub return the value (you call a sub returning the value needed in a void context)
    I would have (re)written it this way :
    #!/usr/local/bin/perl use strict; my $name=myname(); print "my name is $name\n"; sub myname { my $myname = "bill"; return $myname; }

    Now you should see that the var in the sub has nothing to do with the one outsite the sub
    (it's a lexically scoped var, which doesn't exist anymore outside the scope of the sub)

    "Only Bad Coders Badly Code In Perl" (OBC2IP)
      Actually, your first version wouldn't work under strict. The first occurrence of $myname has not yet been declared. Just a point of order... The second is a good example.
Re: use strict and subroutines
by davorg (Chancellor) on Apr 02, 2001 at 19:56 UTC

    In your first version you're defined $myname as a lexical variable that is constrained to the function &myname, therefore it doesn't exist outside the subroutine. In your second example it's defined as a lexical variable constrained to the whole file (i.e. effectively global).

    The best way to do it would be to use the return value from the subroutine which you are currently ignoring, like this:

    #!/usr/local/bin/perl -w use strict; print "my name is ", myname(), "\n"; sub myname { $myname = 'bill'; return $myname; }
    --
    <http://www.dave.org.uk>

    "Perl makes the fun jobs fun
    and the boring jobs bearable" - me

Re: use strict and subroutines
by busunsl (Vicar) on Apr 02, 2001 at 19:52 UTC
    The first version doesn't work, because you declare $myname inside the subroutine. With the end of the subroutine $myname goes out of scope and is not defined in your main program.

    The second version works, because you declare $myname globally, so it goes out of scope at the end of your program.

    You don't have to use return. If you omit it, the last value created in the sub will be returned, in your case the value of $myname.