-
Notifications
You must be signed in to change notification settings - Fork 578
[EXPERIMENT] defer {} syntax #17949
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
FTR, prior work on CPAN includes https://metacpan.org/pod/Scope::OnExit, https://metacpan.org/pod/Scope::Cleanup, and various scope guards like https://metacpan.org/pod/Scope::Guard |
Further discussions about LEAVE have lead to an interesting question - What is the behaviour of exceptions thrown from them? In a simple case such as sub f {
return "123";
LEAVE { die "456" }
} It is relatively easy to argue the case that this should die with "456 at ...", but complications come when the LEAVE block is being executed during stack unwind because another exception is being thrown. sub g {
die "123";
LEAVE { die "456" }
} It is fairly agreeable that invoking g() should die in some manner, but exactly how? Taking a look around other things: Within perl we have many CPAN variations on this theme, almost all of which ultimately rely on My own Syntax::Keyword::Try offers a similar feature in the form of Some other languages choose different ideas. For example, Java takes the latest exception and totally discards an earlier one In the case of the 123+456 case above, I can basically see three possible choices of behaviour: a) Warn about 456, and propagate 123 to caller. This is the current behaviour of SKT's try/finally, and also equivalent to how other CPAN options work) b) Warn about 123, and propagate 456 to caller. This is what most other langs do, except they don't even have a mechanism to warn about 123, so all information about 123 is lost entirely! c) Combine 123 and 456 into a new "double fault" exception representation This one would not be possible without a more standard form in which to represent exceptions in core perl. But see also #17951 (also posted to perl5-porters@ https://www.nntp.perl.org/group/perl.perl5.porters/2020/07/msg257949.html) |
For those following along at home, this idea has been renamed back to |
I think this really lacks flexibility without being able to change a 'return' value from a function, unlike a true 'finally' block. |
I've never heard of such a feature in finally blocks. Do you have examples of prior art that include this feature? I don't find it particularly compelling, regardless; given Perl's notion of return context and dynamic optrees, this sounds quite complex, and I prefer the assurance that the block will indeed not alter any return values. |
For example, java, see http://tpcg.io/PyA94RXu. |
Notable from the Syntax::Keyword::Finally docs, as this differs a bit from the original proposal for LEAVE:
|
Another update: the proposal is now being renamed to lowercase 'defer': https://metacpan.org/pod/Syntax::Keyword::Defer |
I've now turned this issue into a draft RFC at https://github.com/leonerd/Perl-RFCs/blob/rfc0004/rfcs/rfc0004.md |
The initial PR is now merged to blead. There are still some issues with it in odd situations, such as jumping out of a deferred block with |
There are currently no planned extensions to this experiment. It is now currently waiting out its bug-discovery period. |
(copied from https://www.nntp.perl.org/group/perl.perl5.porters/2020/06/msg257611.html )
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 thefinally
keyword, in favour of instead inventing a newLEAVE
phaser block, similar to the Raku ones.In summary: I'd like to add
LEAVE
with syntax which looks like another phaser such asEND
, but runs at the time you leave the block it is placed in:Will output
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:will output
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
still prints, so too would
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?
The text was updated successfully, but these errors were encountered: