Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Missing error under strict

by Pascal666 (Scribe)
on Jul 23, 2019 at 01:50 UTC ( #11103184=perlquestion: print w/replies, xml ) Need Help??

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

Why am I not getting an error message for line 10?
#!/usr/bin/perl -W use strict; use warnings; use feature 'say'; say 'one' until my $one = 1; say $one; ############# this is line 10 until (my $two = 2) { say 'two'; } say $two;
Output:
Global symbol "$two" requires explicit package name at ./strict.pl lin +e 16. Execution of ./strict.pl aborted due to compilation errors.
Commenting out line 16 gives me:
Use of uninitialized value $one in say at ./strict.pl line 10.
This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi

Replies are listed 'Best First'.
Re: Missing error under strict
by LanX (Cardinal) on Jul 23, 2019 at 02:19 UTC
    > Why am I not getting an error message for line 10?

    my is declaring $one for the rest of the scope.

    say 'one' until my $one = 1;

    Scope is the file because post-fix constructs have no surrounding block.

    > Global symbol "$two" requires explicit package name at ./strict.pl line 16.

    The scope here is limited to the loop and won't reach the say

    until (my $two = 2) { say 'two'; } say $two;

    > Commenting out line 16 gives me:

    Then you have no compile time fatals from strict anymore and the script runs

    > Use of uninitialized value $one in say at ./strict.pl line 10.

    that's a run-time warning ...

    ... I'm a bit puzzled and need to run the code, to see why my $one is not initialized

    update

    The condition after until should be executed at least once.

    I can only guess that some kind of weird optimization is happening there.

    Please note that using my in conditional code is considered bad practice and might not be well tested.

    You might have found a bug here.

    update

    My guess is that scope handling is wrong here.

    At runtime a variable should be reset to undef at the end of it's loop-scope.

    Of course this is in conflict with Perl's compile-time behavior of not seeing a scope here.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Missing error under strict
by swl (Priest) on Jul 23, 2019 at 02:07 UTC
      Brian is referring to the side effects of my inside conditional code.

      The OP is using his my in the condition itself which is always executed.

      Most effects are a simple scoping issues.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Missing error under strict (Perlbug: postfix 'until' has inconsistent scope)
by LanX (Cardinal) on Jul 23, 2019 at 11:28 UTC
    I boiled the problem down to this code

    warn $]; #> 5.024001 $null = 1; warn 'never' until $null = 666; warn $null; #> 666 $one = 1; warn 'never' until my $one = 666; # my ! warn $one; #> Warning: something's wrong +at ...

    B::Deparse didn't show anything suspicious

    D:\tmp>perl -MO=Deparse tst_scope.pl warn $]; $null = 1; warn 'never' until $null = 666; warn $null; $one = 1; warn 'never' until my $one = 666; warn $one; tst_scope.pl syntax OK

    I also looked at B::Concise , but couldn't spot a difference in op-code flow.

    My guess is still that until has an inconsistency in scope between compile-time and run-time and is erroneously resetting the lexical variable.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

    update

    PS: I have problem to imagine practical code, where this bug is posing a problem.

      It's a bug definitely. When using if instead of until, it outputs 666.

      > I have problem to imagine practical code, where this bug is posing a problem.

      The bug might manifest in other places, too, where it can cause serious headaches. I've already reported a bug for this Perl version, do you want to have your name mentioned in the Thanks section?

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        > . I've already reported a bug for this Perl version, do you want to have your name mentioned in the Thanks section?

        sure and a link to the thread here please

        something like

        Thanks to Lanx who is normally to busy/lazy to report perlbugs

        ;-)

        > The bug might manifest in other places, too, where it can cause serious headaches.

        Sure that's why I've put so much effort into it. But I think the chances are <1%.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      state declaration, holds

      use strict; use warnings; use feature qw'say state'; {no strict; no warnings; $three = 1; say 'three' until $three++ == 3; } #Use of uninitialized value $two in say at SoPW_11103184.pm line 54 say 'two' until my $two = 2; #say 'owt',$two; say 'one' until state $one = 1; say 'eno',$one; {no strict; no warnings; say $zero until $zero = 9; } say our $minone = 5 until $minone = 8; say $minone; # says '5' continuously #say our $mintwo = 5 until 3 == $mintwo--; #say $mintwo; __END__ three three #say $two #uninit warning eno1 8

      Depending how the scope is declared determines if the assignment is fully evaluated


      Can't find method 'say' in Module 'Died at ....' at ...
        state is a much higher level of headaches and AFAIR not reliable.

        the ... until XXX $var = "x" with XXX a possible declaration is always executed.

        It just happens that $var is reset afterwards.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      > I boiled the problem down to this code

      Here you are initializing a seperate variable before the until, which is getting reset by the my inside the until. In my code I was initializing the variable inside the until, and then attempting to use it after. Seems like two different (but related) bugs to me.

      > PS: I have problem to imagine practical code, where this bug is posing a problem.

      My original code:

      $count++ until my %boxes = fit($count, $quota, @sizes);
      I wasn't sure about the scope when I wrote that line, but figured worst case I would get a compile error and move the my to the line above. Had a hell of a time figuring out why %boxes was always null when I tried to access it later (it should loop until %boxes is not null).
        My intention was to proof a bug in short code.

        There is no possible explanation for an undefined value after the loop. Hence a bug.

        > Here you are initializing a seperate variable before the until, which is getting reset by the my inside the until.

        This statement doesn't really make sense, if the variables are different they can't reset each other.

        As already explained does my have a compile time and a runtime effect, which are inconsistent in this case.

        > Seems like two different (but related) bugs to me.

        No. Everything else was explained.

        > My original code:

        > $count++ until my %boxes = fit($count, $quota, @sizes);

        Thanks, nice example.

        FWIW a workaround is to put the my declaration right before the loop.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Missing error under strict
by Don Coyote (Friar) on Jul 23, 2019 at 13:07 UTC

    Hello Pascal666

    The until BLOCK enters a new lexical scope. When used in BLOCK form. When used as a statement modifier the scope has not entered into a BLOCK. The lexical scope is at the file level so there is no need for strict to complain.

    I was going to suggest using the feature state but this does not change the problem. It does however allow scoping to take place within the block

    Variables lexically scoped with my will be initialised, then get undefined when leaving the scope. As the scope is the body of a loop this re-occurs each iteration

    Variables lexically scoped with state will be initialsed but with enough mana to last till the scope exits at the completion of the loop, whence they will meet their timely fate.

    Change the state and my declarations in the following code, but if you use both my, make sure to uncomment the last three lines of the loop.

    use strict; use warnings; use feature qw'say state'; until ( (state $two = 2)[0] == 2*2*2 ) { state $four = 16; last unless $four; say --$four =~ /\d{2}/ ? "$four" : '0'.$four, ': ',$two++ ; # my my ? uncomment # state $FOUR=64; # $FOUR >= 48 and print '$FOUR: ',$FOUR; # last unless $FOUR--; } say 'owt: ',my $two=2;

    Edited main scope to say file scope, re LanX

      > The lexical scope is still main so there is no need for strict to complain.

      what do you mean with lexical scope "main"?

      If you mean the package main:: , there is nothing like a lexical scope there, packages are global.

      In this case it's the file scope.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11103184]
Approved by LanX
Front-paged by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2020-10-23 23:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My favourite web site is:












    Results (241 votes). Check out past polls.

    Notices?