in reply to Use of uninitialised value... but it is defined ?!

BEGIN blocks run before the rest of the code in the module is even interpreted, so at the time when BEGIN { say __PACKAGE__."::begin $variable"; } runs, the lexical variable $variable has not been created, so the global variable of that name is used, and it has no value; hence the warning.

Solution: don't close over lexical variables in BEGIN blocks.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^2: Use of uninitialised value... but it is defined ?!
by dave_the_m (Monsignor) on Mar 02, 2016 at 07:57 UTC
    lexical variable $variable has not been created, so the global variable of that name is used
    Um ,no: the BEGIN block sees the lexical var, not the package var:
    $x = 'pkg'; my $x; BEGIN { $x = 'lex' } print "$::x $x\n"; #prints pkg lex

    Dave.

      Intriguing.

      So by the time the BEGIN block runs, perl knows enough to know that there is(will be) a lexical $x, sufficient to be able to assign to it; but not enough to have initialised it.

      That's just weird!


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
      In the absence of evidence, opinion is indistinguishable from prejudice.
        'my' has a compile-time and run-time action. The compile-time action is to place a new undef SV in the pad of the sub currently being compiled. This var is immediately available to be closed over when compiling any following subs or BEGIN blocks within the same scope.

        At run time it pushes the current SV in the pad onto the args stack, and adds a note to free the SV on scope exit (and replace with a fresh new one).

        An assignment, such as ..=1 happens at run time of course.

        Dave.

        Not really, you can set a variable's value with arbitrary code, so it's rather consistent of perl to never run it. For example if you had :

        my $first = 1; my @second = grep { ($_+1) % 2 } map { $_ ** 3 } 1..12; my %third = some_function();
        Perl could easily apply the first assignment during compilation, you would kind of expect the second to be run at run time, and the third assignment might either fail or yield the wrong data depending on whether a definition and redefinition of some_function have been seen at that point.

        But perl knowing about the structure of the code (eg. lexicals in a given scope) at compile time is kind of the point.

        BrowserUk: exactly, the order matter. the slot for the variable is created (no errors for undeclared variables) but the assignement not yet. BEGIN blocks jump directly in runtime during the compilation of the program. Quite a good feature!

        Consider the output of the following snippet: perl -wE "my $time = time; BEGIN{say time; sleep 5}; say $time"

        PS the above behaves the same with lexical and package vars:

        perl -E "$time = time; BEGIN{say time; sleep 5}; say $time"

        L*

        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.