Mailing List Archive

Pre-RFC: try/catch/finally and generic finally blocks
In perl 5.34, I implemented a small subset of the full
Syntax::Keyword::Try syntax, being just try/catch, with no finally and
no typed catches.

In perl 5.35.x (I forget which one) we now have `defer` blocks.

Using the same internals that makes them work it would be quite easy to
add the oft-requested try/catch/finally syntax:

try {
say "This happens first";
}
catch ($e) {
say "Oops, a failure happened";
}
finally {
say "This always happens, regardless of success or failure";
}

A try/catch/finally can be implemented basically the same way as if it
was written

{
defer { "finally" code goes here }

try {} catch($e) ... here as normal
}


I have to admit, that even though SKT allows one to write simply
try/finally with no catch, I have never really liked it. The trouble
with it is that as soon as the reader sees the word "try" they might
feel that this is nicely safe code, where any exceptions will be caught
and handled elsewhere. Only when they scroll down, possibly a long way,
and see the *lack of* catch, will they notice it isn't so safe.

try {
## 100 lines here
}
finally {
say "Oh and just do this before you go"
}

For that reason, I'm not sure I want to allow simply try/finally
without a catch.

However, many people like the "later code is written lower down" part
of try/finally. It reads somewhat backwards to see the defer {} block
before the main code:

defer { say "This happens second"; }
say "This happens first";

I wonder therefore about relaxing the syntax a bit to say that
actually, any bare block or a try/catch pair can be followed by a
`finally` block. Thus, we wouldn't write try/finally, but we could write

{
## 100 lines here
}
finally {
say "Oh and just do this before you go"
}

There was no `try` at the top, meaning the reader didn't get lulled
into a false sense of security by thinking there's exception-catching
going on here when there isn't. It's just a bare block, doing what bare
blocks do.

Speaking of do, perhaps you'd also permit

my $result = do { CODE HERE } finally { finish with this };

But that invites questions about value-semantics that I'm not too happy
about asking of what is essentially a control-flow syntax.


As a possible further extension, it could be worth thinking about
whether other kinds of blocks could also permit a trailing `finally` on
them. At the moment I don't have any strong feelings either way, though
offhand I can't immediately imagine what would be the semantics in other
situations:

foreach my $i ( 1 .. 10 ) {
say $i;
}
finally {
say "Done";
}


while( $count-- ) {
say "Nearly...";
}
finally {
say "Go!";
}


if( $x ) { ... }
elsif( $y ) { ... }
else { ... }
finally { say "When does this happen?" }


I don't think we should try too hard to give these meanings, as it's
rather unclear what they should do. Likely those should continue to be
syntax errors for now, and we just focus on the bare-block and
try/catch cases. At least for now.

If there doesn't turn out to be a clear consensus on how to proceed, I
probably won't bother adding anything at this stage. After all, these
postfixed "finally" blocks are really just a different spelling of
things that can already be achieved right now with `defer`; all it does
is moves the order of the lines in the source code so they read better
in top-to-bottom temporal order, and lets you get rid of a single set
of braces. It's a small syntax neatening but nothing truely
groundbreaking.


Thoughts anyone?

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
> I don't think we should try too hard to give these meanings, as it's
rather unclear what they should do. Likely those should continue to be
syntax errors for now, and we just focus on the bare-block and
try/catch cases. At least for now.

I fully agree with this paragraph.
Bare blocks and try/catch pair fit best with finally.
Thanks.


On Tue, Oct 19, 2021 at 10:25 PM Paul "LeoNerd" Evans <
leonerd@leonerd.org.uk> wrote:

> In perl 5.34, I implemented a small subset of the full
> Syntax::Keyword::Try syntax, being just try/catch, with no finally and
> no typed catches.
>
> In perl 5.35.x (I forget which one) we now have `defer` blocks.
>
> Using the same internals that makes them work it would be quite easy to
> add the oft-requested try/catch/finally syntax:
>
> try {
> say "This happens first";
> }
> catch ($e) {
> say "Oops, a failure happened";
> }
> finally {
> say "This always happens, regardless of success or failure";
> }
>
> A try/catch/finally can be implemented basically the same way as if it
> was written
>
> {
> defer { "finally" code goes here }
>
> try {} catch($e) ... here as normal
> }
>
>
> I have to admit, that even though SKT allows one to write simply
> try/finally with no catch, I have never really liked it. The trouble
> with it is that as soon as the reader sees the word "try" they might
> feel that this is nicely safe code, where any exceptions will be caught
> and handled elsewhere. Only when they scroll down, possibly a long way,
> and see the *lack of* catch, will they notice it isn't so safe.
>
> try {
> ## 100 lines here
> }
> finally {
> say "Oh and just do this before you go"
> }
>
> For that reason, I'm not sure I want to allow simply try/finally
> without a catch.
>
> However, many people like the "later code is written lower down" part
> of try/finally. It reads somewhat backwards to see the defer {} block
> before the main code:
>
> defer { say "This happens second"; }
> say "This happens first";
>
> I wonder therefore about relaxing the syntax a bit to say that
> actually, any bare block or a try/catch pair can be followed by a
> `finally` block. Thus, we wouldn't write try/finally, but we could write
>
> {
> ## 100 lines here
> }
> finally {
> say "Oh and just do this before you go"
> }
>
> There was no `try` at the top, meaning the reader didn't get lulled
> into a false sense of security by thinking there's exception-catching
> going on here when there isn't. It's just a bare block, doing what bare
> blocks do.
>
> Speaking of do, perhaps you'd also permit
>
> my $result = do { CODE HERE } finally { finish with this };
>
> But that invites questions about value-semantics that I'm not too happy
> about asking of what is essentially a control-flow syntax.
>
>
> As a possible further extension, it could be worth thinking about
> whether other kinds of blocks could also permit a trailing `finally` on
> them. At the moment I don't have any strong feelings either way, though
> offhand I can't immediately imagine what would be the semantics in other
> situations:
>
> foreach my $i ( 1 .. 10 ) {
> say $i;
> }
> finally {
> say "Done";
> }
>
>
> while( $count-- ) {
> say "Nearly...";
> }
> finally {
> say "Go!";
> }
>
>
> if( $x ) { ... }
> elsif( $y ) { ... }
> else { ... }
> finally { say "When does this happen?" }
>
>
> I don't think we should try too hard to give these meanings, as it's
> rather unclear what they should do. Likely those should continue to be
> syntax errors for now, and we just focus on the bare-block and
> try/catch cases. At least for now.
>
> If there doesn't turn out to be a clear consensus on how to proceed, I
> probably won't bother adding anything at this stage. After all, these
> postfixed "finally" blocks are really just a different spelling of
> things that can already be achieved right now with `defer`; all it does
> is moves the order of the lines in the source code so they read better
> in top-to-bottom temporal order, and lets you get rid of a single set
> of braces. It's a small syntax neatening but nothing truely
> groundbreaking.
>
>
> Thoughts anyone?
>
> --
> Paul "LeoNerd" Evans
>
> leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
> http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
>
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
"Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
[...]
: try {
: ## 100 lines here
: }
: finally {
: say "Oh and just do this before you go"
: }
[...]
: {
: ## 100 lines here
: }
: finally {
: say "Oh and just do this before you go"
: }
:
:There was no `try` at the top, meaning the reader didn't get lulled
:into a false sense of security by thinking there's exception-catching
:going on here when there isn't. It's just a bare block, doing what bare
:blocks do.

On the other hand, there is also the possibility now that you end up
with:

{
# couple of lines here
}
# 100 lines of comments here
finally { ... }

I think it's unwise to try to mitigate every case of "100 lines here",
it seems like a short road to madness. But if you want to avoid it in
this case, I think you'd need yet another keyword. I'm not convinced
that the language is improved by tacking an optional continuation onto
bare blocks.

Either way, I do think we should be encouraging Perl developers to write
their code so as to minimize confusion, eg by factoring away "100 lines
here".

Hugo
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
* hv@crypt.org <hv@crypt.org> [2021-10-19 21:49:47 +0100]:

> "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
> [...]
> : try {
> : ## 100 lines here
> : }
> : finally {
> : say "Oh and just do this before you go"
> : }
> [...]
> : {
> : ## 100 lines here
> : }
> : finally {
> : say "Oh and just do this before you go"
> : }

Replying to Hugo's comment only to honor it; but in the case of
the bare block this seems like a NOOP unless "finally" implies a
"wait" or waitpid for thing, but I don't know what things that
could be other than a child process spawned by either C<fork> or
an explict background shell command via C<system> or C<``> or
C<qx//>, etc.

LABEL:
{
# do stuff
# spawn a child proc
}
finally {
# do more stuff but what's
# the state of child process?
}

1. when does `finally` get executed, does it wait for child pid?
2. does LABEL: work as expected if one does, `next LABEL;`?

Cheers
Brett

> :
> :There was no `try` at the top, meaning the reader didn't get lulled
> :into a false sense of security by thinking there's exception-catching
> :going on here when there isn't. It's just a bare block, doing what bare
> :blocks do.
>
> On the other hand, there is also the possibility now that you end up
> with:
>
> {
> # couple of lines here
> }
> # 100 lines of comments here
> finally { ... }
>
> I think it's unwise to try to mitigate every case of "100 lines here",
> it seems like a short road to madness. But if you want to avoid it in
> this case, I think you'd need yet another keyword. I'm not convinced
> that the language is improved by tacking an optional continuation onto
> bare blocks.
>
> Either way, I do think we should be encouraging Perl developers to write
> their code so as to minimize confusion, eg by factoring away "100 lines
> here".
>
> Hugo

--
--
oodler@cpan.org
oodler577@sdf-eu.org
SDF-EU Public Access UNIX System - http://sdfeu.org
irc.perl.org #openmp #pdl #native
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Tue, Oct 19, 2021 at 7:45 PM Oodler 577 via perl5-porters <
perl5-porters@perl.org> wrote:

> * hv@crypt.org <hv@crypt.org> [2021-10-19 21:49:47 +0100]:
>
> > "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
> > [...]
> > : try {
> > : ## 100 lines here
> > : }
> > : finally {
> > : say "Oh and just do this before you go"
> > : }
> > [...]
> > : {
> > : ## 100 lines here
> > : }
> > : finally {
> > : say "Oh and just do this before you go"
> > : }
>
> Replying to Hugo's comment only to honor it; but in the case of
> the bare block this seems like a NOOP unless "finally" implies a
> "wait" or waitpid for thing, but I don't know what things that
> could be other than a child process spawned by either C<fork> or
> an explict background shell command via C<system> or C<``> or
> C<qx//>, etc.
>
> LABEL:
> {
> # do stuff
> # spawn a child proc
> }
> finally {
> # do more stuff but what's
> # the state of child process?
> }
>
> 1. when does `finally` get executed, does it wait for child pid?
> 2. does LABEL: work as expected if one does, `next LABEL;`?
>

Forking has no relevance to the concept. The difference finally makes, as
with defer, is that it runs when the associated scope is exited, even if
it's done so via an exception, loop control, etc.

-Dan
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
2021-10-20 4:07 Elvin Aslanov <rwp.primary@gmail.com> wrote:

> > I don't think we should try too hard to give these meanings, as it's
> rather unclear what they should do. Likely those should continue to be
> syntax errors for now, and we just focus on the bare-block and
> try/catch cases. At least for now.
>
> I fully agree with this paragraph.
> Bare blocks and try/catch pair fit best with finally.
> Thanks.
>

Me too.

try/catch pair with finally.

try {
say "This happens first";
}
catch ($e) {
say "Oops, a failure happened";
}
finally {
say "This always happens, regardless of success or failure";
}

And Bare block with finally

{
## 100 lines here
}
finally {
say "Oh and just do this before you go"
}
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
* Dan Book <grinnz@gmail.com> [2021-10-19 20:48:15 -0400]:

> On Tue, Oct 19, 2021 at 7:45 PM Oodler 577 via perl5-porters <
> perl5-porters@perl.org> wrote:
>
> > * hv@crypt.org <hv@crypt.org> [2021-10-19 21:49:47 +0100]:
> >
> > > "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
> > > [...]
> > > : try {
> > > : ## 100 lines here
> > > : }
> > > : finally {
> > > : say "Oh and just do this before you go"
> > > : }
> > > [...]
> > > : {
> > > : ## 100 lines here
> > > : }
> > > : finally {
> > > : say "Oh and just do this before you go"
> > > : }
> >
> > Replying to Hugo's comment only to honor it; but in the case of
> > the bare block this seems like a NOOP unless "finally" implies a
> > "wait" or waitpid for thing, but I don't know what things that
> > could be other than a child process spawned by either C<fork> or
> > an explict background shell command via C<system> or C<``> or
> > C<qx//>, etc.
> >
> > LABEL:
> > {
> > # do stuff
> > # spawn a child proc
> > }
> > finally {
> > # do more stuff but what's
> > # the state of child process?
> > }
> >
> > 1. when does `finally` get executed, does it wait for child pid?
> > 2. does LABEL: work as expected if one does, `next LABEL;`?
> >
>
> Forking has no relevance to the concept. The difference finally makes, as
> with defer, is that it runs when the associated scope is exited, even if
> it's done so via an exception, loop control, etc.

I guess I don't understand the value of providing this for a bare block,
and the only value I can see in any other block structure is to extend
scope "one more time".

# currently
my $i;
for $i (1..10) {
# do stuff
}
if ($i < 10) {
print qq{Loop exited early!\n};
}

versus

# with 'finally'
for my $i (1..10) {
# do stuff
}
finally {
if ($i < 10) {
print qq{Loop exited early!\n};
}
}

Similarly, I see value in extending this to the block form of eval,

local $@;
my $ret = eval {
my $inner_var = q{asdf};
#... do stuf that might die
}
finally {
print qq{$inner_var};
}

#$@ and $ret available here, $inner_var is not
#...

It also seems to provide the corollary to do { .. } while (), which provides
an in scope "pre step" versus a basic while () { ... }.

So maybe to be consist, the "finally" on a "while" should be like,

while (...) {

}
do {

}

Or maybe, "finally" should just be "done" for all,

while (...) {

}
done {

}

or

try {

}
catch {

}
done {

}

or

for my $i (1..10) {

}
done {

}

etc

Thanks,
Brett

>
> -Dan

--
--
oodler@cpan.org
oodler577@sdf-eu.org
SDF-EU Public Access UNIX System - http://sdfeu.org
irc.perl.org #openmp #pdl #native
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Wed, 20 Oct 2021 at 12:57, Oodler 577 via perl5-porters <
perl5-porters@perl.org> wrote:

> I guess I don't understand the value of providing this for a bare block,
> and the only value I can see in any other block structure is to extend
> scope "one more time".
>
> # currently
> my $i;
> for $i (1..10) {
> # do stuff
> }
> if ($i < 10) {
> print qq{Loop exited early!\n};
> }
>

Consider `die`, `next OUTER` or `return` in the `# do stuff` section. Any
of those would give different results for the finally vs. code-after-loop
versions.
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Tue, 19 Oct 2021 19:25:04 +0100
"Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:

> Using the same internals that makes them work it would be quite easy
> to add the oft-requested try/catch/finally syntax:
>
> try {
> say "This happens first";
> }
> catch ($e) {
> say "Oops, a failure happened";
> }
> finally {
> say "This always happens, regardless of success or failure";
> }
>
> A try/catch/finally can be implemented basically the same way as if it
> was written
>
> {
> defer { "finally" code goes here }
>
> try {} catch($e) ... here as normal
> }

I've now written a (currently-draft) PR to implement specifically this
bit of try/catch/finally syntax:

https://github.com/Perl/perl5/pull/19285

It doesn't yet address such questions as `finally` on bare blocks or
other situations.

It also doesn't address the question of how to deparse compiled code
using this syntax, as it is currently implemented by the same optree as
a `defer` block would use, and is thus indistinguishable, in much the
same way that "A and B" and "B if A" would deparse the same way.

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
* Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> [2021-12-16 22:22:56 +0000]:

> On Tue, 19 Oct 2021 19:25:04 +0100
> "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
>
> > Using the same internals that makes them work it would be quite easy
> > to add the oft-requested try/catch/finally syntax:
> >
> > try {
> > say "This happens first";
> > }
> > catch ($e) {
> > say "Oops, a failure happened";
> > }
> > finally {
> > say "This always happens, regardless of success or failure";
> > }
> >
> > A try/catch/finally can be implemented basically the same way as if it
> > was written
> >
> > {
> > defer { "finally" code goes here }
> >
> > try {} catch($e) ... here as normal
> > }

Pardon me if I still have not gotten this clear in the space between
my ears, but why not call it "finally"? "defer" begs the question,
"defer until when?"; "finally" asks and answers this quite succinctly.

Cheers,
Brett

>
> I've now written a (currently-draft) PR to implement specifically this
> bit of try/catch/finally syntax:
>
> https://github.com/Perl/perl5/pull/19285
>
> It doesn't yet address such questions as `finally` on bare blocks or
> other situations.
>
> It also doesn't address the question of how to deparse compiled code
> using this syntax, as it is currently implemented by the same optree as
> a `defer` block would use, and is thus indistinguishable, in much the
> same way that "A and B" and "B if A" would deparse the same way.
>
> --
> Paul "LeoNerd" Evans
>
> leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
> http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/

--
--
oodler@cpan.org
oodler577@sdf-eu.org
SDF-EU Public Access UNIX System - http://sdfeu.org
irc.perl.org #openmp #pdl #native
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Fri, 17 Dec 2021 20:43:31 +0000
Oodler 577 via perl5-porters <perl5-porters@perl.org> wrote:

> but why not call it "finally"? "defer" begs the question,
> "defer until when?"; "finally" asks and answers this quite succinctly.

Because many many (many) languages already have try/catch/finally in
this same shape, and many many languages already have defer in this
same shape.

That familiarity in users' expectations is good.

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
2021-12-17 7:23 Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> wrote:

> On Tue, 19 Oct 2021 19:25:04 +0100
> "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
>
> > Using the same internals that makes them work it would be quite easy
> > to add the oft-requested try/catch/finally syntax:
> >
> > try {
> > say "This happens first";
> > }
> > catch ($e) {
> > say "Oops, a failure happened";
> > }
> > finally {
> > say "This always happens, regardless of success or failure";
> > }
> >
> > A try/catch/finally can be implemented basically the same way as if it
> > was written
> >
> > {
> > defer { "finally" code goes here }
> >
> > try {} catch($e) ... here as normal
> > }
>
> I've now written a (currently-draft) PR to implement specifically this
> bit of try/catch/finally syntax:
>
> https://github.com/Perl/perl5/pull/19285
>
> Whether to allow try/finally without a catch block
>

I think allowing try/finally results in being used in the production at
experimental status.

If you haven't decided yet, it is good to forbid try/finally at first
implementation.
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
2021-12-21 8:54 Yuki Kimoto <kimoto.yuki@gmail.com> wrote:

>
>
> 2021-12-17 7:23 Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> wrote:
>
>> On Tue, 19 Oct 2021 19:25:04 +0100
>> "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
>>
>> https://github.com/Perl/perl5/pull/19285
>
>
> How best to deparse these, as they are implemented as { defer {FINALLY}
try/catch }
> How to fix up failure messages - they currently complain about ... in
"defer" block

I think users are surprised that finally block raises the error message
"defere" block.

Could you add a "finally" flag to the C structure of the block for "defer"?
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Thu, 16 Dec 2021 22:22:56 +0000
"Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:

> It also doesn't address the question of how to deparse compiled code
> using this syntax, as it is currently implemented by the same optree
> as a `defer` block would use, and is thus indistinguishable, in much
> the same way that "A and B" and "B if A" would deparse the same way.

This is now done and ready for review:

https://github.com/Perl/perl5/pull/19285

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
2022-1-19 8:54 Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> wrote:

> On Thu, 16 Dec 2021 22:22:56 +0000
> "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
>
> > It also doesn't address the question of how to deparse compiled code
> > using this syntax, as it is currently implemented by the same optree
> > as a `defer` block would use, and is thus indistinguishable, in much
> > the same way that "A and B" and "B if A" would deparse the same way.
>
> This is now done and ready for review:
>
> https://github.com/Perl/perl5/pull/19285
>
>
It seems to be good for me.

I'm reading t/op/try.t.

I have a question.

Are "next" and "redo" a compilation error in the finally block?
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Wed, 19 Jan 2022 10:38:09 +0900
Yuki Kimoto <kimoto.yuki@gmail.com> wrote:

> Are "next" and "redo" a compilation error in the finally block?

Nothing is currently a compile-time error (though I have plans to add
that sometime before 5.336 release); they're all detected at runtime.

next/last/redo all act the same way, so I didn't add three tests for
each on the hope that the `last` one is sufficient for them all.

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Wed, Jan 19, 2022 at 5:48 AM Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

>
> next/last/redo all act the same way, so I didn't add three tests for
> each on the hope that the `last` one is sufficient for them all.
>


My expectations of what next/last/redo would do in a finally block are as
follows:


- last jumps to the end of the finally block
- redo starts the finally block over (not the exception handler, but you
should be able to get there with goto label)
- next jumps to the test for the outer interator, if any, as if it was
stated outside of the construct. Why is next even an issue in
try/catch/finally? it isn't an interator.

or does "act the same way" just have to do with scope cleanup, and "the
same way" means "no change to how they act" ?

--
"Lay off that whiskey, and let that cocaine be!" -- Johnny Cash
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
2022-1-19 20:48 Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> wrote:

> On Wed, 19 Jan 2022 10:38:09 +0900
> Yuki Kimoto <kimoto.yuki@gmail.com> wrote:
>
> > Are "next" and "redo" a compilation error in the finally block?
>
> Nothing is currently a compile-time error (though I have plans to add
> that sometime before 5.336 release); they're all detected at runtime.
>
> next/last/redo all act the same way, so I didn't add three tests for
> each on the hope that the `last` one is sufficient for them all.
>
>
Thank you. I understand next/last/redo all act the same way.
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Tue, 18 Jan 2022 23:54:18 +0000
"Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:

> On Thu, 16 Dec 2021 22:22:56 +0000
> "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
>
> > It also doesn't address the question of how to deparse compiled code
> > using this syntax, as it is currently implemented by the same optree
> > as a `defer` block would use, and is thus indistinguishable, in much
> > the same way that "A and B" and "B if A" would deparse the same
> > way.
>
> This is now done and ready for review:
>
> https://github.com/Perl/perl5/pull/19285

This is now merged and will hopefully be available in the next release
- coming any day now :)

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Wed, 19 Jan 2022 13:46:58 -0600
David Nicol <davidnicol@gmail.com> wrote:

> My expectations of what next/last/redo would do in a finally block
> are as follows:
>
>
> - last jumps to the end of the finally block

`last` doesn't jump out of an if, else, try, catch, or defer block. Why
should `finally` be any different?

> - redo starts the finally block over (not the exception handler,
> but you should be able to get there with goto label)

Same question as above.

> - next jumps to the test for the outer interator, if any, as if it
> was stated outside of the construct. Why is next even an issue in
> try/catch/finally? it isn't an interator.

`next` is only a problem for the same reason that any of the loopex,
goto or return are a problem. They're a problem because they cause a
control flow jump directly out of the block.

This is a problem for two reasons:

1) Annoying "this is hard to implement" reasons.

2) Fundamental semantic "this is meaningless" reasons.

Consider

sub f {
defer { return 123; }
die "Ooops\n";
}

What should be the result of calling f()? Once the `die` line is hit,
we're committed to throwing an exception. The defer block gets invoked
as part of scope unwind, but should it be permitted to `return`? Does
it cause the call to f() to return that value and stop the exception
propagating? In effect we've now cancelled the exception.

This isn't the way that defer- or finally-alike constructions work in
basically any other language. It would be a bad model for us to follow.

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
consider

use strict;
use warnings; ### get "exiting subroutine via ..." warnings
my $rflag;
print "checkpoint A\n";
for my $i (1 .. 5){
print "i is $i\n";
$i == 1 and next;
$rflag++ or redo;
$i == 3 and last;
}

print "checkpoint B\n";

sub mynext { print "checkpoint BN\n";next }
sub myredo { print "checkpoint BR\n";redo }
sub mylast { print "checkpoint BL\n";last }

my $rflag2;
for my $i (1 .. 5){
print "i is $i\n";
$i == 1 and mynext;
$rflag2++ or myredo;
$i == 3 and mylast;
}
print "checkpoint C\n";
__END__

i therefore expect next, redo, or last in a defer block to next, last, or
redo the calling loop if any -- but at the end of the block with the defer
in it, if we ever get there.

On Fri, Jan 21, 2022 at 11:18 AM Paul "LeoNerd" Evans <
leonerd@leonerd.org.uk> wrote:

> On Wed, 19 Jan 2022 13:46:58 -0600
> David Nicol <davidnicol@gmail.com> wrote:
>
> > My expectations of what next/last/redo would do in a finally block
> > are as follows:
> >
> >
> > - last jumps to the end of the finally block
>
> `last` doesn't jump out of an if, else, try, catch, or defer block. Why
> should `finally` be any different?
>
> > - redo starts the finally block over (not the exception handler,
> > but you should be able to get there with goto label)
>
> Same question as above.
>
> > - next jumps to the test for the outer interator, if any, as if it
> > was stated outside of the construct. Why is next even an issue in
> > try/catch/finally? it isn't an interator.
>
> `next` is only a problem for the same reason that any of the loopex,
> goto or return are a problem. They're a problem because they cause a
> control flow jump directly out of the block.
>
> This is a problem for two reasons:
>
> 1) Annoying "this is hard to implement" reasons.
>
> 2) Fundamental semantic "this is meaningless" reasons.
>
> Consider
>
> sub f {
> defer { return 123; }
> die "Ooops\n";
> }
>
> What should be the result of calling f()? Once the `die` line is hit,
> we're committed to throwing an exception. The defer block gets invoked
> as part of scope unwind, but should it be permitted to `return`? Does
> it cause the call to f() to return that value and stop the exception
> propagating? In effect we've now cancelled the exception.
>
> This isn't the way that defer- or finally-alike constructions work in
> basically any other language. It would be a bad model for us to follow.
>
> --
> Paul "LeoNerd" Evans
>
> leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
> http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
>


--
"Lay off that whiskey, and let that cocaine be!" -- Johnny Cash
Re: Pre-RFC: try/catch/finally and generic finally blocks [ In reply to ]
On Fri, 21 Jan 2022 12:35:59 -0600
David Nicol <davidnicol@gmail.com> wrote:

> i therefore expect next, redo, or last in a defer block to next,
> last, or redo the calling loop if any -- but at the end of the block
> with the defer in it, if we ever get there.

Again I ask you to be very clear in the face of exceptions.

How do you expect the following to behave?

foreach my $i ( 1 .. 5 ) {
print "Starting $i\n";
defer {
print "Deferring $i\n";
next;
}
die "Failing $i";
}

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/