RFC: LEAVE phasers

TL;DR: I want to add LEAVE phaser blocks.


I'm trying to simplify the design of a try/catch syntax out of
Syntax::Keyword::Try so it can be moved into core perl. One thing I
think we can get rid of is the `finally` keyword, in favour of instead
inventing a new `LEAVE` phaser block, similar to the Raku ones.

In summary: I'd like to add `LEAVE` with syntax which looks like
another phaser such as `END`, but runs at the time you leave the block
it is placed in:

  sub f {
    print 1;
    LEAVE { print 3; }

    print 3;
  }

  f();

Will output

  123

Furthermore, a LEAVE phaser inside something like a foreach loop would
run every time you leave the block in order to run a new one:

  foreach (qw( a b c )) {
    print "Start($_)";
    LEAVE { print "End($_)"; }

    more code here...
  }

will output

  Start(a)End(a)Start(b)End(b)Start(c)End(c)

Seems simple enough.

It is important to note that a LEAVE block is similar to an END block,
in that the mere presence of that syntax is enough to queue it for
being run, regardless of whether the line of code it's on was actually
"reached". Thus, just as in

  exit 0;
  END { say "Ending the program now" }

still prints, so too would

  sub f {
    return;
    LEAVE { say "Leaving the function now" }
  }

If we had a LEAVE phaser (totally independent of any thoughts of
try/catch), it reduces the scope of that work considerably and makes it
easier to work out how to implement.

Thoughts?

-- 
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/
0
leonerd
6/27/2020 12:16:54 PM
perl.perl5.porters 48128 articles. 1 followers. Follow

3 Replies
14 Views

Similar Articles

[PageSpeed] 29

--00000000000048c14b05a91af6f3
Content-Type: text/plain; charset="UTF-8"

On Sat, 27 Jun 2020 at 14:17, Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> TL;DR: I want to add LEAVE phaser blocks.
>
>
> I'm trying to simplify the design of a try/catch syntax out of
> Syntax::Keyword::Try so it can be moved into core perl. One thing I
> think we can get rid of is the `finally` keyword, in favour of instead
> inventing a new `LEAVE` phaser block, similar to the Raku ones.
>
> In summary: I'd like to add `LEAVE` with syntax which looks like
> another phaser such as `END`, but runs at the time you leave the block
> it is placed in:
>
>   sub f {
>     print 1;
>     LEAVE { print 3; }
>
>     print 3;
>   }
>
>   f();
>
> Will output
>
>   123
>
> Furthermore, a LEAVE phaser inside something like a foreach loop would
> run every time you leave the block in order to run a new one:
>
>   foreach (qw( a b c )) {
>     print "Start($_)";
>     LEAVE { print "End($_)"; }
>
>     more code here...
>   }
>
> will output
>
>   Start(a)End(a)Start(b)End(b)Start(c)End(c)
>
> Seems simple enough.
>
> It is important to note that a LEAVE block is similar to an END block,
> in that the mere presence of that syntax is enough to queue it for
> being run, regardless of whether the line of code it's on was actually
> "reached". Thus, just as in
>
>   exit 0;
>   END { say "Ending the program now" }
>
> still prints, so too would
>
>   sub f {
>     return;
>     LEAVE { say "Leaving the function now" }
>   }
>
> If we had a LEAVE phaser (totally independent of any thoughts of
> try/catch), it reduces the scope of that work considerably and makes it
> easier to work out how to implement.
>
> Thoughts?
>
>
How will LEAVE and continue to work together?


> --
> Paul "LeoNerd" Evans
>
> leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
> http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/
>

--00000000000048c14b05a91af6f3
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr"><br></div><br><div class=3D"gmail_quote">=
<div dir=3D"ltr" class=3D"gmail_attr">On Sat, 27 Jun 2020 at 14:17, Paul &q=
uot;LeoNerd&quot; Evans &lt;<a href=3D"mailto:leonerd@leonerd.org.uk">leone=
rd@leonerd.org.uk</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote"=
 style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);p=
adding-left:1ex">TL;DR: I want to add LEAVE phaser blocks.<br>
<br>
<br>
I&#39;m trying to simplify the design of a try/catch syntax out of<br>
Syntax::Keyword::Try so it can be moved into core perl. One thing I<br>
think we can get rid of is the `finally` keyword, in favour of instead<br>
inventing a new `LEAVE` phaser block, similar to the Raku ones.<br>
<br>
In summary: I&#39;d like to add `LEAVE` with syntax which looks like<br>
another phaser such as `END`, but runs at the time you leave the block<br>
it is placed in:<br>
<br>
=C2=A0 sub f {<br>
=C2=A0 =C2=A0 print 1;<br>
=C2=A0 =C2=A0 LEAVE { print 3; }<br>
<br>
=C2=A0 =C2=A0 print 3;<br>
=C2=A0 }<br>
<br>
=C2=A0 f();<br>
<br>
Will output<br>
<br>
=C2=A0 123<br>
<br>
Furthermore, a LEAVE phaser inside something like a foreach loop would<br>
run every time you leave the block in order to run a new one:<br>
<br>
=C2=A0 foreach (qw( a b c )) {<br>
=C2=A0 =C2=A0 print &quot;Start($_)&quot;;<br>
=C2=A0 =C2=A0 LEAVE { print &quot;End($_)&quot;; }<br>
<br>
=C2=A0 =C2=A0 more code here...<br>
=C2=A0 }<br>
<br>
will output<br>
<br>
=C2=A0 Start(a)End(a)Start(b)End(b)Start(c)End(c)<br>
<br>
Seems simple enough.<br>
<br>
It is important to note that a LEAVE block is similar to an END block,<br>
in that the mere presence of that syntax is enough to queue it for<br>
being run, regardless of whether the line of code it&#39;s on was actually<=
br>
&quot;reached&quot;. Thus, just as in<br>
<br>
=C2=A0 exit 0;<br>
=C2=A0 END { say &quot;Ending the program now&quot; }<br>
<br>
still prints, so too would<br>
<br>
=C2=A0 sub f {<br>
=C2=A0 =C2=A0 return;<br>
=C2=A0 =C2=A0 LEAVE { say &quot;Leaving the function now&quot; }<br>
=C2=A0 }<br>
<br>
If we had a LEAVE phaser (totally independent of any thoughts of<br>
try/catch), it reduces the scope of that work considerably and makes it<br>
easier to work out how to implement.<br>
<br>
Thoughts?<br>
<br></blockquote><div><br></div><div>How will LEAVE and continue to work to=
gether?</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:=
1ex">
-- <br>
Paul &quot;LeoNerd&quot; Evans<br>
<br>
<a href=3D"mailto:leonerd@leonerd.org.uk" target=3D"_blank">leonerd@leonerd=
..org.uk</a>=C2=A0 =C2=A0 =C2=A0 |=C2=A0 <a href=3D"https://metacpan.org/aut=
hor/PEVANS" rel=3D"noreferrer" target=3D"_blank">https://metacpan.org/autho=
r/PEVANS</a><br>
<a href=3D"http://www.leonerd.org.uk/" rel=3D"noreferrer" target=3D"_blank"=
>http://www.leonerd.org.uk/</a>=C2=A0 |=C2=A0 <a href=3D"https://www.tindie=
..com/stores/leonerd/" rel=3D"noreferrer" target=3D"_blank">https://www.tind=
ie.com/stores/leonerd/</a><br>
</blockquote></div></div>

--00000000000048c14b05a91af6f3--
0
happy
6/28/2020 1:35:38 AM
--00000000000056002305a9417b9c
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Sat, 27 Jun 2020 at 14:17, Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> TL;DR: I want to add LEAVE phaser blocks.
>

Yes! A simple addition with a lot of usefulness.

On Sat, Jun 27, 2020 at 9:35 PM Branislav Zahradn=C3=ADk <happy.barney@gmai=
l.com>
wrote:

> How will LEAVE and continue to work together?
>

I imagine the same way as guard-using solutions do:

*continue on while/for/foreach:*

$ perl -e'
   use feature qw( say );

   sub DESTROY { $_[0]->$*->(); }
   sub on_scope_exit(&) { my $cb =3D shift; bless(\$cb) }


   for (qw( foo bar )) {
      my $guard =3D on_scope_exit { say "guard $_" };
      say;
   } continue {
      say "continue";
   }
'
foo
guard foo
continue
bar
guard bar
continue

*continue in when:*

$ perl -e'
   use feature      qw( say );
   use experimental qw( switch );

   sub DESTROY { $_[0]->$*->(); }
   sub on_scope_exit(&) { my $cb =3D shift; bless(\$cb) }

   given (1) {
      when ($_ =3D=3D 1) {
         my $guard =3D on_scope_exit { say "bar" };
         say "foo";
         continue;
      }

      when ($_ =3D=3D 1) {
         say "baz";
      }
   }
'
foo
bar
baz

--00000000000056002305a9417b9c
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr"></div><div class=3D"gmail_quote"><div dir=
=3D"ltr" class=3D"gmail_attr">On Sat, 27 Jun 2020 at 14:17, Paul &quot;LeoN=
erd&quot; Evans &lt;<a href=3D"mailto:leonerd@leonerd.org.uk" target=3D"_bl=
ank">leonerd@leonerd.org.uk</a>&gt; wrote:<div dir=3D"ltr"><div class=3D"gm=
ail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">TL;DR: I want =
to add LEAVE phaser blocks.<br></blockquote></div></div><div><br></div><div=
>Yes! A simple addition with a lot of usefulness.<br></div>

</div><div dir=3D"ltr" class=3D"gmail_attr"><br></div>
<div class=3D"gmail_quote">On Sat, Jun 27, 2020 at 9:35 PM Branislav Zahrad=
n=C3=ADk &lt;<a href=3D"mailto:happy.barney@gmail.com">happy.barney@gmail.c=
om</a>&gt; wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div=
 dir=3D"ltr"><div class=3D"gmail_quote"><div>How will LEAVE and continue to=
 work together?</div></div></div></blockquote><div><br></div><div>I imagine=
 the same way as guard-using solutions do:=C2=A0 <br></div><div><br></div><=
b>continue on while/for/foreach:</b></div><div class=3D"gmail_quote"><br></=
div><div class=3D"gmail_quote">$ perl -e&#39;<br>=C2=A0 =C2=A0use feature q=
w( say );<br><br>=C2=A0 =C2=A0sub DESTROY { $_[0]-&gt;$*-&gt;(); }<br>=C2=
=A0 =C2=A0sub on_scope_exit(&amp;) { my $cb =3D shift; bless(\$cb) }<br><br=
><br>=C2=A0 =C2=A0for (qw( foo bar )) {<br>=C2=A0 =C2=A0 =C2=A0 my $guard =
=3D on_scope_exit { say &quot;guard $_&quot; };<br>=C2=A0 =C2=A0 =C2=A0 say=
;<br>=C2=A0 =C2=A0} continue {<br>=C2=A0 =C2=A0 =C2=A0 say &quot;continue&q=
uot;;<br>=C2=A0 =C2=A0}<br>&#39;<br>foo<br>guard foo<br>continue<br>bar<br>=
guard bar<br>continue</div><div class=3D"gmail_quote"><br></div><div class=
=3D"gmail_quote">
<div class=3D"gmail_quote"><b>continue in when:</b></div><div class=3D"gmai=
l_quote"><br></div><div class=3D"gmail_quote">$ perl -e&#39;<br>=C2=A0 =C2=
=A0use feature =C2=A0 =C2=A0 =C2=A0qw( say );<br>=C2=A0 =C2=A0use experimen=
tal qw( switch );<br><br>=C2=A0 =C2=A0sub DESTROY { $_[0]-&gt;$*-&gt;(); }<=
br>=C2=A0 =C2=A0sub on_scope_exit(&amp;) { my $cb =3D shift; bless(\$cb) }<=
br><br>=C2=A0 =C2=A0given (1) {<br>=C2=A0 =C2=A0 =C2=A0 when ($_ =3D=3D 1) =
{<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0my $guard =3D on_scope_exit { say &q=
uot;bar&quot; };<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0say &quot;foo&quot;;<=
br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0continue;<br>=C2=A0 =C2=A0 =C2=A0 }<br=
><br>=C2=A0 =C2=A0 =C2=A0 when ($_ =3D=3D 1) {<br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0say &quot;baz&quot;;<br>=C2=A0 =C2=A0 =C2=A0 }<br>=C2=A0 =C2=A0}<=
br>&#39;<br>foo<br>bar<br>baz</div></div><br></div></div>

--00000000000056002305a9417b9c--
0
ikegami
6/29/2020 11:32:59 PM
On Sun, 28 Jun 2020 03:35:38 +0200
Branislav Zahradn=C3=ADk <happy.barney@gmail.com> wrote:

> How will LEAVE and continue to work together?

A fun question. I have to say I don't think I've ever used a `continue`
block and I'd forgotten they exist, but yes they definitely should be
considered here.

I suspect it would probably work something like the following:

  use v5.10;
  foreach my $x (1, 2) {
    say "Doing $x";
    LEAVE { say "Did $x"; }
  } continue {
    say "Continuing after $x";
    LEAVE { say "Continued after $x"; }
  }


  Doing 1
  Did 1
  Continuing after 1
  Continued after 1
  Doing 2
  Did 2
  Continuing after 2
  Continued after 2

--=20
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/
0
leonerd
7/3/2020 9:49:28 PM
Reply: