in reply to Logic for importing and strict vars?

why the fourth of these examples is an error

I'd say it's in accordance with strict (emphasis mine):

strict vars

This generates a compile-time error if you access a variable that was neither explicitly declared (using any of my, our, state, or use vars ) nor fully qualified.

(Edit: to re-phrase, maybe it's more clear -- was neither explicitly declared nor is fully qualified.)

Thus, no surprise that next 2 lines fail:

perl -wMstrict -e "$::x=0; $x++" # not OK perl -wMstrict -e "package foo; $foo::x=0; $x++" # not OK

Next 2 lines are your examples -- it's strange 2nd (your third) doesn't fail:

perl -wMstrict -e "BEGIN{*::x=\$a} $x++" # not OK (1) perl -wMstrict -e "BEGIN{package foo; *::x=\$a} $x++" # OK (2)

It has something to do with BEGIN:

perl -wMstrict -e "{package foo; *::x=\$a} $x++" # not OK

the deparsed output is an insult:

C:\>perl -MO=Deparse -wMstrict -e "{package foo; *::x=\$a} $x++" Variable "$x" is not imported at -e line 1. Global symbol "$x" requires explicit package name (did you forget to d +eclare "my $x"?) at -e line 1. -e had compilation errors. BEGIN { $^W = 1; } use strict; { package foo; *main::x = \$a; } $main::x++;

But also with "main" package. Next 2 are symmetrical with examples (1) and (2), just with "bar" instead of "main", but both OK now:

perl -wMstrict -e "BEGIN{package bar; *bar::x=\$a} package bar; $x++" + # not OK perl -wMstrict -e "BEGIN{package foo; *bar::x=\$a} package bar; $x++" + # OK

Edit 2: Actually, replacing "main" with "bar" doesn't change anything (fixed one of the lines above).

Replies are listed 'Best First'.
Re^2: Logic for importing and strict vars?
by Veltro (Hermit) on Feb 27, 2019 at 13:14 UTC
    It has something to do with BEGIN

    I have found this information:

    BEGIN: A BEGIN code block is executed as soon as possible, that is, the moment it is completely defined, even before the rest of the containing file (or string) is parsed

    So I suspect that that means that in case the BEGIN is not there the parser will detect the variable $x before it is created. In case the BEGIN is there, it is guarantied to execute that block first, so before it sees $x (or in this case actually $main::x) and by that time it exists because the block has already been executed.

    edit: It even looks like that BEGIN turns off certain warnings for this reason:

    perl -MO=Deparse -wMstrict -e "{ package bla { *::x=\$a } }" Name "main::x" used only once: possible typo at -e line 1. ...
    perl -MO=Deparse -wMstrict -e "BEGIN { package bla { *::x=\$a } }" # No problem
      It has something to do with BEGIN
      In case the BEGIN is there, it is guarantied to execute that block first, so before it sees $x (or in this case actually $main::x) and by that time it exists because the block has already been executed.

      Yes, I concur - and an interesting point regarding the warnings. I assume they don't occur because otherwise they'd get triggered by the import mechanism regularly, but it'd be interesting to find any docs on that, too...

Re^2: Logic for importing and strict vars?
by haukex (Archbishop) on Feb 28, 2019 at 08:45 UTC
    it's strange 2nd (your third) doesn't fail ... Actually, replacing "main" with "bar" doesn't change anything (fixed one of the lines above).

    Yes, that's the logic that I was looking for "official" documentation on - the difference is, as tye said, "when the variable slot of a glob gets assigned to by code compiled into another package".