Front page | perl.perl5.porters |
Postings from January 2017
my $x if 0 [ was: Re: Deprecation plans]
Thread Previous
|
Thread Next
From:
Dave Mitchell
Date:
January 11, 2017 14:11
Subject:
my $x if 0 [ was: Re: Deprecation plans]
Message ID:
20170111141123.GI4206@iabyn.com
On Tue, Jan 10, 2017 at 06:40:20PM -0500, Ricardo Signes wrote:
> Cool, thanks for working on this! A few notes:
>
> * Sawyer X <xsawyerx@gmail.com> [2017-01-08T13:22:55]
> > * Deprecated use of my() in false conditional: Deprecated in 5.10.0,
> > remove in 5.30.0.
>
> This came up in the past and "remove" seemed like not the straightforward and
> preferred solution:
>
> http://markmail.org/thread/uslcig4mwn47pmyn
>
> I am not presenting an opinion, only a link to history.
The longer history of this is that back in feb 2004, I added a general
deprecation warning for any 'my $foo if condition' style code - given that
it was likely to trigger the buggy 'lexical var not cleared on scope
exit and old value still available on next call' behaviour:
commit dc9aa44637d2171ba3efbf36c71e8591a7ce05d7
commit edd7382e985077dac6582d6406b3a16fa5fff0e9
Then in these 2004 threads:
http://nntp.perl.org/group/perl.perl5.porters/88928
http://nntp.perl.org/group/perl.perl5.porters/89114
it was found that the new warning made CPAN *very* noisy, and also that it
was buggy: it missed warning on some cases.
So I replaced it with the more restrictive 'Deprecated use of my() in
false conditional', which only warned on a *compile-time* false, i.e.
specifically 'my $x if 0', so that it would discourage people from
exploiting the bug to implement poor-man's state vars. So if we ever fixed
or changed the buggy behaviour, people would be less likely to be relying
on that behaviour.
commit 7921d0f22732c0609e6c9d21be9aaf6e52f99e6b
From that perspective, I see no problem in making any compile-time
situations where it currently warns into compile-time croaks.
If we ever fix or change the behaviour, then we could remove the croak.
As for fixing it, that's quite hard. At one point long ago I had a
proof-of-concept fix that essentially moved the run-time behaviour of each
my() to the top of each scope; so this code:
{
...
my $x = 1;
...
my $y = 2;
...
}
would behave at runtime (but without changing the compile time scope of
each var) conceptually like
{
(my $x, $y,....);
...
$x = 1;
...
$y = 2;
...
}
This worked. The issue with it was that in some circumstances it could
impose a significant performance penalty. Consider:
while (<>) {
next unless /(some)_(rare)_(occurrence)/;
# lots of code to process these rare lines:
my ($some, $rare, $occurrence) = ($1, $2, $3);
...
my ($a, $foo, @b, %c);
...
my ($even, $more, $lexicals); # stuff further down the block
...
}
Previously the loop was fast because it only has to make a note on the
savestack to clear variables when the rare line is hit. Now it always has
to do it for every line.
It's analogous to this old behaviour:
while (<>) {
next unless /(some)_(rare)_(occurrence)/;
local($some, $rare, $occurrence) = ($1, $2, $3);
local($a, $foo, @b, %c);
local($even, $more, $lexicals);
...
}
being changed to this:
while (<>) {
local($some, $rare, $occurrence);
local($a, $foo, @b, %c);
local($even, $more, $lexicals);
next unless /(some)_(rare)_(occurrence)/;
($some, $rare, $occurrence) = ($1, $2, $3);
...
}
If we *were* to change the behaviour, then we'd probably need a further
deprecation and warning cycle to cover some of the other cases where a my
is being skipped at runtime - i.e. something like my original reverted
commit. Perhaps CPAN would be less noisy these days.
--
This is a great day for France!
-- Nixon at Charles De Gaulle's funeral
Thread Previous
|
Thread Next