in reply to Re^7: "my" declaration problem
in thread "my" declaration problem

You can replace the use of Guard by the following class:

package Guard; sub DESTROY { $_[0]->() }; sub guard (&) { bless $_[0] => __PACKAGE__ };

Here is the complete program, without that scary XS:

package Guard; sub DESTROY { $_[0]->() }; package main; use File::Temp 'tempfile'; sub guard (&) { bless $_[0] => 'Guard'; }; sub frobnicate { my ($fh,$name) = tempfile(); print {$fh} "Hello"; close $fh; my $atexit = guard { print "Removing '$name'"; unlink $name; }; my ($fh,$name) = tempfile(); print {$fh} "World"; close $fh; my $atexit = guard { print "Removing '$name'"; unlink $name; }; print "Important processing here"; } print "Frobnicating"; frobnicate(); print "Frobnicating done, and cleaned up"; __END__ Frobnicating Important processing here Removing 'C:\Users\Corion\AppData\Local\Temp\w2guL0aAIx' Removing 'C:\Users\Corion\AppData\Local\Temp\mtR1B1FxN3' Frobnicating done, and cleaned up

I think Guard lives in a very similar incarnation in some other module whose name escapes me. Maybe tilly wrote it, and I think another similar one was posted recently on blogs.perl.org.

Update: The blogs.perl.org incarnation is Golang's 'defer' in Perl.

tillys module is ReleaseAction. There also are AtExit, and its SEE ALSO section provides lots of other, similar modules.

Replies are listed 'Best First'.
Re^9: "my" declaration problem
by LanX (Saint) on Apr 25, 2017 at 21:05 UTC
    How is it possible that $atexit holds 2 objects which are both destroyed at scopes end?

    Even if this somehow works, then it's highly implementation dependent and could break in a future Perl version.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

      How is it possible that $atexit holds 2 objects which are both destroyed at scopes end?

      Because there are 2 $atexit variables - a masked one, and a masking one created later.

      This is all to fullfill what hath been written:

      "my" variable $var masks earlier declaration in same scope

      Since it masks that variable - and does not replace it since this would mean destroying the current my variable of that name, the scope of the masked variable ends when the masking ends - because the scope of the masking variable ends - which is: at scope end.

      IMHO this is not an implementation specific detail, but part of the the design of my and perl scopes, thus part of the language.

      perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

      I think this works because lexical variables are only cleaned up at the end of their scope, as every lexical variable ends up in the CvPADLIST structure (cf. pad.c and perlintern where I found this). The CvPADLIST is an array and not a hash, as far as I understand it.

      Please provide an example where the code is not broken.

      I showed what you requested, an example where the code is demonstrably not broken.

        > an example where the code is demonstrably not broken.

        yes you did, thank you!

        But my opinion holds, for me this depends too much on implementation details.

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

      Do not forget the runtime effect of my. See "goto" memory leak. (And maybe this for a lovely show of side effects.)

      Perl cannot and must not destroy objects before their scope ends. Implementation detail is the order in which global objects are destroyed.