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

Perl has some - IMHO buggy - behavior if a lexical declaration happens in the head and not the body of a compound construct like if(HEAD){BODY} .

The compile-time scope ends right after the BODY is closed, hence the lexical is not anymore declared.

But the run-time destruction will only happen if the outer-scope - that's at least the file-scope° - is finished.

Any reason why?

In my book that's a design flow at least.

DEMO:

use strict; use warnings; use Data::Dump qw/pp dd/; $\="\n"; our $PHASE=0; { if ( my $x = bless {name=>"extra block"}, "TEST" ) { $PHASE=1; print $x; } } # DESTRUCTION $PHASE=2; # line 16 if ( my $x = bless {name=>"head if"}, "TEST" ) { $PHASE=3; print $x; } # NO DESTRUCTION # --- uncomment for compile-time error # print $x; print ""; $PHASE=4; print ""; # line 32 package TEST; use Carp; sub DESTROY { my ( $self ) = @_ ; carp "DESTROY <x: $self->{name}> <PHASE: $::PHASE>"; }

will produce this output

C:/Strawberry/perl/bin\perl.exe -w d:/tmp/pm/berny_open.pl DESTROY <x: extra block> <PHASE: 1> at d:/tmp/pm/berny_open.pl line 16 +. DESTROY <x: head if> <PHASE: 4> at d:/tmp/pm/berny_open.pl line 32. TEST=HASH(0x1ca7e8) TEST=HASH(0x1ca8f0)

DISCLAIMER: This was just discussed at German.PM online meeting today and was motivated by this SO-Discussion.

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery

updates

Replies are listed 'Best First'.
Re: Scope difference between compile-time and run-time
by dave_the_m (Monsignor) on Jun 01, 2021 at 19:19 UTC
    It's a bug, but one of those more likely to break things by fixing it than by leaving it as is.

    Dave.

      Out of curiosity:

      Is it at least theoretically feasible to fix it as part of a feature such that a use 5.36; would avoid that bug?

      I'm not saying this has high priority ...

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        I've not looked closely, but I assume yes.

        Dave.

Re: Scope difference between compile-time and run-time
by choroba (Archbishop) on Jun 01, 2021 at 19:29 UTC
    Interestingly, changing if to while (and adding a last before the closing curly brace) moves the second destruction to line 28 (the previous print, but I guess it just means the end of the loop.

    I've read somewhere it's an unwanted consequence of the implementation of else which needs to access the variables from the if condition, so they need to live a bit longer. In that case, I'd expect continue to have the same effect, but it clearly doesn't work that way.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      I didn't replicate it but the SO example was with for not if

      One might build test-cases by evaling code with all possible compounds.

      I suppose the effect is also visible in the OP-tree.

      I seem to remember we discussed it before, and that it's related to different phasing with the scope's scratch-pad where lexicals live.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

Re: Scope difference between compile-time and run-time ( if( my $x = ... ) {...} )
by choroba (Archbishop) on Jun 02, 2021 at 21:44 UTC
    See also Missing error under strict which reported a similar behaviour and led to a similar discussion.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]