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

I'm facing a peculiar problem. If i run the follwoing lines of code I get the output.

my $type="w"; &print_summary; sub print_summary { if($type=~/w/) { print "hello\n"; } }

output: hello

But if try to run like this:

sub print_summary { if($type=~/w/) { print "hello\n"; } } my $type="w"; &print_summary;

It doesn't give me any output. What could be the reason behind this as in both cases the varibale is declared before the function call is made?

20060505 Janitored by Corion: Added formatting, code tags

Replies are listed 'Best First'.
Re: Problem with function
by Corion (Patriarch) on May 05, 2006 at 13:36 UTC

    You only think that both versions of your code use the same variable, but the second version does not. What happens in fact is, that your sub print_summary uses the global variable $type ($main::type, to be verbose), while you later on declare a lexical variable $type. The strict pragma tells you about that, which is why you should use it:

    use strict; sub print_summary { if ($type =~ /w/) { print "Hello\n"; }; }; my $type = "w"; print_summary;

    Here, Perl raises an error that you're using an undeclared variable $type in print_summary, which tells you that declaring the variable too late prevents Perl from seeing it.

Re: Problem with function
by jonadab (Parson) on May 05, 2006 at 13:47 UTC

    If $type is a variable that really needs to be available to your entire program, then you should put the declaration at the top of the file. However, in this case, I'd suggest that you consider passing it as an argument to your function:

    sub print_summary { my ($type) = @_; if($type=~/w/) { print "hello\n"; } } # ... later ... print_summary("world");

    Actually, what I'd probably do is more along these lines...

    sub summary { my ($type) = @_; if($type=~/w/) { return "Hello, "; } elsif ($type =~ /h/) { return "world!\n"; } } # ... later ... print summary("world"); print summary("hello");

    Notice here that the function returns the string to be printed, rather than printing it. This makes the function more reusable in the event that you need to send the results somewhere other than standard output, e.g., write them to a file, send them over a socket, or capture them to a string for subsequent processing.


    Sanity? Oh, yeah, I've got all kinds of sanity. In fact, I've developed whole new kinds of sanity. Why, I've got so much sanity it's driving me crazy.
      If you're going to pass $type into the function I'd do this:
      sub summary { my $type = shift || return '';
      To avoid warnings later when someone forgets and tries to
      print summary();
        I think in that case I'd prefer to *have* the warnings.
Re: Problem with function
by japhy (Canon) on May 05, 2006 at 13:46 UTC
    This is why, in 99% of cases, you should always pass the variables your function needs TO the function.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: Problem with function
by blazar (Canon) on May 05, 2006 at 13:39 UTC
    • use <code> tags;
    • use strict; # and perl will help you to understand;
    • use warnings; # as well!
Re: Problem with function
by billh (Pilgrim) on May 05, 2006 at 15:05 UTC
    The scope of the lexical variable $type is from its declaration to the end of the file, not including the body of the function where you're trying to access it.
    Bill H
    perl -e 'print sub { "Hello @{[shift]}!\n" }->("World")'
A reply falls below the community's threshold of quality. You may see it by logging in.