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

Hi, I've got something like this in a script:
use strict; my $wibble; do "include.pl"; print $wibble;
Now include.pl looks like this: $wibble = "fred"; When I run this I get no output. It looks like 'my' is scoping $wibble to global, but the $wibble = "fred" in include.pl is not evaluated. I suppose I want to implicitly import $wibble from include.pl by using use, but use "include.pl" causes a syntax error. Interestingly if I leave use strict off, then the program prints "fred", as I want. I therefore tried turning off strict for a moment by doing:
no strict "vars"; do "include.pl" use strict "vars";
but that didn't sort it. It's probably something really obvious, can anyone see what I need to do? I don't want to leave strict off completely. Thanks, dch.

Replies are listed 'Best First'.
Re: strict/do question
by shmem (Chancellor) on Nov 24, 2006 at 13:20 UTC
    From perlfaq8:
    1. do $file is like eval `cat $file`, except the former
    1. searches @INC and updates %INC.
    2. bequeaths an *unrelated* lexical scope on the eval'ed code.

    The lexical scope is unrelated. So, the my variable of one file is that file's variable (that's what 'my' means). Use our in both files, and your script will run fine with use strict and work like expected.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      using our was the ticket... now where's my camel?... :-) Really appreciate the help. You monks rock!
Re: strict/do question
by Tanktalus (Canon) on Nov 24, 2006 at 14:54 UTC

    Note that converting to "our" means that you're now using a global variable instead of a lexical variable. This entirely changes the scope of your variable so that now everyone can see it. That may be ok. If it isn't, perhaps you should look at a configuration file that you can read in and put its values into your lexicals yourself.

    That said, I just don't like do FILE. do BLOCK is fine, but do FILE feels dangerous. You're better off renaming it to include.pm, and then being able to use or require include. (Well, don't actually make it all lower-case - that's reserved for pragmas, by convention. Better to use Include.pm instead.) At least, that's my opinion.

      Note that converting to "our" means that you're now using a global variable instead of a lexical variable.

      Well, not quite.. our makes not global globals, but package globals (what if there's no package?). Also, it makes file globals whose scope spans packages in the same file. And our allows for sharing variables between files. But yes, our should be used with caution.

      That said, I just don't like do FILE. do BLOCK is fine, but do FILE feels dangerous.

      But require is IMHO just an enhanced do, and use an enhanced require. Aren't those functions nested like a Matryoshka doll? And innermost - there's just the eevil string eval: eval `cat $file`. I guess do, require and use are equally dangerous...

      Please correct me if I'm wrong. (either me or perlfaq8 ;-)

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

        If there is no package, it's ::, or main::. But that's the definition of "global" in Perl - a package variable is visible everywhere, even if you have to explicitly specify the package, while a lexical is not. It's similar to C++'s namespaces - sure, you can have more than one global variable, as long as they're in different namespaces / packages, but they're still global.

        The danger in do is just that Perl 5 has conventions. And those conventions are about useing modules, not evaling file contents. And because these are the conventions, that's what people are used to. When you buck those conventions, you introduce an error-prone area where nuances of the implementation (which are generously documented, but who looks at documentation? ;->) can bite you. For example, it seems common that people expect that do FILE will import lexicals (despite the docs). But I've not yet seen someone assume that from a use MODULENAME that has, as per convention, a package declaration at the top.

        That's not to say "never use do FILE" - just be sure you know what you're doing when you do so. It's an uncommon idiom, and, usually, a more common idiom would not only serve the same purpose, but be more maintainable. Even though I can't think of a good reason to use do FILE over either a proper module or a config file (depending on what the use is) doesn't mean I'm discounting the possibility. ;-)

Re: strict/do question
by ikegami (Patriarch) on Nov 24, 2006 at 16:47 UTC

    use strict and my $wibble are not seen by include.pl. do s executes it in a different lexical scope.

    That means that $wibble = "fred"; actually does $main::wibble = "fred"; (assuming main is the current package).

    Because of the my $wibble (not because of use strict), the main program's $wibble refers to a lexical var and not to $main::wibble. If you were to print $main::wibble, you'd see "fred".

    The most straightforward way to solve the problem is to use eval instead of do. eval runs code in the same lexical scope as the eval itself (instead of creating an entirely new scope like do), so the code sees and obeys directives such as use strict and my $wibble.

    use strict; use warnings; my $include_file = 'include.pl'; my $wibble; eval do { open(my $fh, '<', $include_file) or die("Unable to open include \"$include_file\": $!\n"); local $/; <$fh> }; die $@ if $@; print $wibble;
    # include.pl $wibble = 'fred'; # Uncommenting the following line causes a strict error. #$wobble = 'joe';
Re: strict/do question
by Anonymous Monk on Nov 24, 2006 at 12:54 UTC
      In depth stuff - that's great thx - I've printed it off for bedtime reading :-)
Re: strict/do question
by Anonymous Monk on Nov 24, 2006 at 13:07 UTC
      Thanks for the link!