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

I'm getting differing behaviour on two chunks of code that are (according to PerlDoc) supposed to be identical.

This works:

my @fields = qw( opffile spec twig twigroot twigmeta error ); require fields; fields->import(@fields);

This doesn't:

my @fields = qw( opffile spec twig twigroot twigmeta error ); use fields @fields;

Could someone please explain why?

Replies are listed 'Best First'.
Re: When is "use module" not the same as require+import?
by Corion (Patriarch) on Sep 18, 2008 at 18:21 UTC

    Not exactly. The documentation says:

    It is exactly equivalent to
    BEGIN { require Module; Module->import( LIST ); }

    And the BEGIN{} block makes all the difference. The BEGIN means that the code is run immediately after Perl has reached the closing curly brace. Which is well before Perl runs the code that initializes your @fields array. Putting the assignment to @fields into a(nother) BEGIN block would alleviate that problem.

      Whee, except that comes with the additional interesting quirk that you can't actually declare the array in the BEGIN, because of course it will go out of scope between that block and the fresh BEGIN block implicit in use. What a mess. Looks like require+import is actually cleaner-looking.

      Thanks, both to you and moritz below, since the versioning issue is also good to know.

        It seems that you can get around the scoping issue by not leaving the BEGIN block:
        BEGIN { my @fields = qw/field1 field2/; use fields @fields; } my $self = fields::new; $self->{field1} = 'value1';
        works just fine for me. It may fairly be argued that this is not much different from putting a require and import inside the BEGIN, though.

        UPDATE: ikegami correctly points out that I must not have tested what I thought I tested, because this code doesn't work. Sorry. I think Bloodnok's solution (adapted to use fields) works, though.

        An alternative to get round the scoping problem is...
        use vars qw/%a_hash/; BEGIN { $a_hash{key} = qw/val/; } . .
        A user level that continues to overstate my experience :-))
Re: When is "use module" not the same as require+import?
by moritz (Cardinal) on Sep 18, 2008 at 18:46 UTC
    Answering your question in the title, not your real question (which Corion already answered accurately):

    There's another difference which the documentation is silent about, and that's the version of the module:

    $ perl -wle 'use CGI 100' CGI version 100 required--this is only version 3.15 at -e line 1. BEGIN failed--compilation aborted at -e line 1. $ perl -wle 'BEGIN { require CGI; CGI->import(100) };' # (no output)

    From the documentation there's no obvious way to require a minimal version of a module (expect checking it manually, and die if it's not large enough).

      There is an easy way.

      >perl -wle "BEGIN { require CGI; CGI->VERSION(100) };" CGI version 100 required--this is only version 3.15 at -e line 1. BEGIN failed--compilation aborted at -e line 1.

      Also, Exporter emulates this behaviour, so your code would have worked if CGI used Exporter.

      >perl -e"{ package Mod; $VERSION='3.15'; } Mod->import(100)" >perl -e"{ package Mod; $VERSION='3.15'; use Exporter; @ISA='Exporter' +; } Mod->import(100)" Mod version 100 required--this is only version 3.15 at c:/Progs/perl58 +8/lib/Exporter/Heavy.pm line 121.
Re: When is "use module" not the same as require+import?
by ikegami (Patriarch) on Sep 19, 2008 at 19:23 UTC
    The problem:
    my @fields = qw( opffile spec twig twigroot twigmeta error ); # This stmt is only executed once # the whole file is compiled. use fields @fields; # This line is executed as soon # as it is compiled.

    Workaround:

    my @fields; BEGIN { @fields = qw( opffile spec twig twigroot twigmeta error ); } # This block is executed as soon # as this line is compiled. use fields @fields; # This line is executed as soon # as it is compiled.