develooper Front page | perl.perl5.porters | Postings from June 2021

Re: RFC 0004 - defer {} syntax

Thread Previous | Thread Next
From:
shmem
Date:
June 17, 2021 09:14
Subject:
Re: RFC 0004 - defer {} syntax
Message ID:
alpine.DEB.2.21.2106171058130.4388@mgm-net.de
From the keyboard of Ben Bullock [17.06.21,10:44]:

[...]
> To clarify, in terms of your example, my query is about this:
> 
> sub superduper 
> {
>    if ($resource->acquire) {
>        defer { $resource->release }
>        if ($resource->failure) {
>              # Case failure: Either way it runs here
>              return undef;
>         }
>         if (0 == -1) {
>              # Case exception: Either way it runs here
>              die "Oh no I have failed";
>          }
>          if ($resource->blocks) {
>               # Case next: Either way it runs here.
>               next;
>           }
>        # Case if block finishes: At the moment it runs here <----------- why does it run
> here?
>    }
>    # Case enclosing loop finishes: <------------- Why not run here instead?
>    return 1;
> }
> 
> > Do you have any examples in mind where this would be a better fit than the
> scoped-to-block implementation currently described, though?
> 
> The "defer" is called within the "if" statement then runs at the end of the if statement,
> I'm wondering why it can't run at the end of the loop instead. Then we can do things like
> this:
> 
> while (1) {
>    if ($resource->too_busy) {
>         defer {
>              $resource->close_some_connections;
>         }
>         # Don't want to clean up yet.
>     }
>     $resource->do_something;
>     $resource->do_another_thing;
>     # Clean up here with the defer statements.
> }
> 
> The reason I'm saying it is because I can't see a big advantage from running at the end of
> an if block, but I can see an advantage from being able to run defers conditionally.
> 
>

Maybe "defer" should follow the semantics of "next" and "last", which would
allow to say "defer BLOCK" and "defer LABEL BLOCK", with a special label or
label modifier named ":outer" (or ":after" ?).

sub foo {
     my $lim = shift;
     my (@l, $c);
     QWURX: for my $x (1..5) {
         defer { say "candidate $x" };
         return if $x > $lim;
         my $y = $x << 1;
         if ($x % 2) {
             defer :outer { say "y = $y" }; #2, same as defer QWURX
             $c++;
             defer :outer QWURX { say "$c. even number" }; #3 also: defer QWURX :outer { }
             say "x % 2";
         }
         say "x = $x";
         # defer block #2 runs here
         # defer block #1 runs here
     }
     # defer block(s) #3 run(s) here
}

So, a deferred block can be hooked to a labelled block (or a bare label) at its
end or outside of it. Maybe the modfier ":return" would be useful, to hook the
deferred blocks to the end of or return from a subroutine.

0--gg-

-- 
_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                               /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About