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

Hello Monks, I am trying to create local variable and get following error message while in use strict mode.

#!/usr/bin/perl -w use strict; ref_test1(); sub ref_test1 { local $type="connect"; print "Here in ref_test1.\n"; ref_test2(); } sub ref_test2 { print "Type: $type\n"; print "Here in ref_test2\n"; }

OUTPUT:

Global symbol "$type" requires explicit package name at ./zz.pl line 8.

Global symbol "$type" requires explicit package name at ./zz.pl line 15.

Replies are listed 'Best First'.
Re: Unable to declare local variable with "use strict".
by ikegami (Patriarch) on Mar 26, 2010 at 20:33 UTC

    local doesn't declare a variable. It just makes a temporarily backup of one.

    You can use our to effectively disable strict 'vars' for a variable.

    #!/usr/bin/perl -w use strict; our $type; ref_test1(); sub ref_test1 { local $type="connect"; print "Here in ref_test1.\n"; ref_test2(); } sub ref_test2 { print "Type: $type\n"; print "Here in ref_test2\n"; }
    or
    #!/usr/bin/perl -w use strict; ref_test1(); sub ref_test1 { local our $type="connect"; print "Here in ref_test1.\n"; ref_test2(); } sub ref_test2 { our $type; print "Type: $type\n"; print "Here in ref_test2\n"; }

    However, the following is better because it's more loosely coupled:

    #!/usr/bin/perl -w use strict; ref_test1(); sub ref_test1 { print "Here in ref_test1.\n"; ref_test2("connect"); } sub ref_test2 { my ($type) = @_; print "Type: $type\n"; print "Here in ref_test2\n"; }
      So, I can not use local with use strict? I would use our but I will be using it in threads and I don't feel safe to use because there is no scope for it. Is it safe to use our with threads? Thanks for Everyones response.

        So, I can not use local with use strict?

        I just gave two examples that use local and strict.

        I don't feel safe to use because there is no scope for it.

        Local only works on package (global) variables. You can't use local on lexical (scoped) variables.

        (Well, it also works hash elements and array elements, but I don't see how that could be useful here.)

        Is it safe to use our with threads?

        In Perl threads, each thread has its own variables unless you share them explicitly. This applies to both lexical (scoped) and package (global) variables.

        Strict makes you declare your variables. Local does not declare a variable...
        it makes a backup copy of an existing global variable, and that global is still global.

        my declares a local variable. my is what you want to use.

        I think you should first make up your mind what kind of variables you would like to have. We should not use the term "local variable" in Perl, since it is not clear what this means. Perl has two type of variables: Lexical variables, and package global variables. Which one would you like to use?

        Lexical variables are declared using my or state - the latter only if you are using Perl 5.10, and if feature 'state' is enabled.

        Package global variables do not need to be declared. They can be declared using our. If you decide not to declare them, and have strict in effect (which is for sure a good idea), you have to qualify them with the full package name.

        local is a function which operates on package global variables. Hence if you use it, and have strict in effect, you need to qualify the variable name with the package.

        My impression is that a lot of the confusion about your posting arose, because you did not explain in the first place what kind of variable you want to use, so some people thought you are interested in lexicals (and suggested to use my), while others thought you want to have package globals (and suggested to use our).

        -- 
        Ronald Fischer <ynnor@mm.st>
        So, I can not use local with use strict?
        Sure you can. Note that anyone with a reply suggesting you replace the 'local' with 'my' doesn't understand why you are getting the error.

        The problem is the extension of the scope. You do local $var in a certain scope. But the other use is in a different scope. That is the cause of the error. Replacing the local with my doesn't solve that.

Re: Unable to declare local variable with "use strict".
by kennethk (Abbot) on Mar 26, 2010 at 20:30 UTC
    You may find a read through of local informative, particularly the first line:

    You really probably want to be using my instead, because local isn't what most people think of as "local".

    This might also be confusion on your part about what strict does. As best as I can tell, your code (maybe) does what you expect by declaring a $type variable at the script level and swapping your local statement to a my - this results in creating a localized $type variable in ref_test1 and a closure around the script-level variable in ref_test2:

    #!/usr/bin/perl -w use strict; my $type = "some line"; ref_test1(); sub ref_test1 { my $type="connect"; print "Here in ref_test1.\n"; ref_test2(); } sub ref_test2 { print "Type: $type\n"; print "Here in ref_test2\n"; } __END__ Here in ref_test1. Type: some line Here in ref_test2
Re: Unable to declare local variable with "use strict".
by doug (Pilgrim) on Mar 27, 2010 at 14:57 UTC

    It looks like fuzzy thinking to me. You have two subroutines and you want then to share a variable, but you don't want that variable visible anywhere else. The answer to this is closures.

    Since subroutines form a closure, the easiest way is to declare ref_test2() inside the body of ref_test1(). ref_test2() will have access to everything ref_test1() does, Note that creating a named subroutine puts a global entry in the symbol table, ref_test2() could still be called from outside of ref_test1() and still see the exact same variables.

    But I don't like nested subroutines under any circumstances, so I wouldn't go there. I'd do it like this:

    { # start closure my $type; sub ref_test1() { ... } sub ref_test2() { ... } } # end of closure

    which allows both to read/write/whatever $type as much as they like, yet $type is still invisible to the outside world.

    - doug

    PS: Someone posted that since ref_test1() was calling ref_test2() directly, then you should pass $type as a parameter, and I agree completely. I'm guessing that this example is simplified, and that in the real example ref_test2() can be called from other places too.

Re: Unable to declare local variable with "use strict".
by planetscape (Chancellor) on Mar 26, 2010 at 20:30 UTC

    my

    HTH,

    planetscape
      Changing the local into a my will give the same error.