in reply to 'finally' block in Perl?

While perl does not have a formal mechanism for finally blocks, you can indeed easily emulate them with an object that has a destructor. (update: MeowChow beat me by pointing out an easier/already-in-CPAN way to do this.)

#>>> DummyDestructor.pm package DummyDestructor; use strict; use vars qw(@ISA @EXPORT); require Exporter; @ISA = qw(Exporter); @EXPORT = qw(make_finally); sub make_finally (\&) { return bless $_[0], __PACKAGE__; } sub DESTROY { $_[0]->(); } #>>> some perl script use DummyDestructor; ... { ... code ... my $final = make_finally { ... code ... } # beware! # no access to @_ in finally ... code ... }

A more straight-forward alternative is eval and a bare block:

sub f { my @return; ... more code ... # vars needed in "finally" must be # defined here! eval{{ ... and more ... # instead of return $retval you'd need: @return = $retval and last; ... yet more code ... }} ... do clean up stuff here ... die $@ if $@; return @return; }

Replies are listed 'Best First'.
Re^2: 'finally' block in Perl?
by matvore (Initiate) on Jan 06, 2019 at 15:19 UTC
    Why do you have two layers of { curly braces } delimiting the eval block?

      perlsyn describes how last, redo, or next won't work (or won't do what one might expect) in if, unless, do{}, sub{}, and eval{}. last says: "Note that a block by itself is semantically identical to a loop that executes once. Thus last can be used to effect an early exit out of such a block." - a solution also described in perlsyn: "Loop control statements don't work in an if or unless, since they aren't loops. You can double the braces to make them such, though. ... This is caused by the fact that a block by itself acts as a loop that executes once".

      Update: Note how in the following, the first part prints "A" and "B" (and a warning about exiting eval via last), but not "D", while the second part prints "X", "Y", and "Z".

      { print "A\n"; eval { print "B\n"; last; print "C\n"; }; print "D\n"; } { print "W\n"; eval {{ print "X\n"; last; print "Y\n"; }}; print "Z\n"; }
        Ah right, because the original question wanted to support multiple return places. Thank you for the detailed reply! I also realized that the first reply called it a "bare block" which I could have used to do a Google search had I read it more carefully. I found this when looking for a way to handle clean-up in a function that may exit early due to an exception, not a return. In my case, the "eval" approach (without the bare block) with a "die $@ if $@" is satisfactory so I don't have to pull in an extra dependency. Hypothetically, the "early return" case can be handled by wrapping early-returnable logic in a separate function, though I can see that this may be cumbersome in some contexts.
Re: Re: 'finally' block in Perl?
by John M. Dlugosz (Monsignor) on Jul 22, 2001 at 05:38 UTC
    Those are exactly the two methods I was thinking of. So what do people really do in this situation?