Good news : things are not broken that much :)
First thing, I get *lots* of warnings "Deprecated use of my() in
conditional" in the test suites.
Secondly, here are the failures I got so far:
PAR 0.79_07 (Autrijus knows about this)
libxml-perl 0.07 (notably XML::Parser::PerlSAX)
XML::Twig 3.13
the last two seem to be related to encoding stuff. We may
hit backward incompatibilities here; or bugs.
Hmm, I thought there might be!
Do we
a) chicken out before 5.9.1
b) chicken out before 5.10
c) have the courage of our convictions?
My vote is provisionally (c), reverting to (b) if there's too much
uproar.
--
"I do not resent critisism, even when, for the sake of emphasis,
it parts for the time with reality".
-- Winston Churchill, House of Commons, 22nd Jan 1941.
I'd say the decision should be if the warning is actually catching
potential problems or if its just being annoying. Much of the problem can
go away by supplying patches to those module authors effected so they
can fix things before 5.10.
--
Michael G Schwern sch...@pobox.com http://www.pobox.com/~schwern/
If you got the wax out of your ears you could hear the twister picking up
the trailer park of your future!
Well, writing
my $foo = $bar if $quux;
# and never ever using $foo if $quux is false
is bug-free.
Considering this, I think we could, er, chicken out the current warning,
and (d) replace it by a run-time one, produced only in the above case
when $quux is false.
Downside of (d) : this wouldn't be a deprecation warning, so we
wouldn't change the meaning of this expression in 5.12.
> (c) Even if there are bug free potential uses of this feature, it seems
> like it is still a bug waiting to happen. Every time I've done it, it
> was a bug that did happen. Accidentally. I sure wish I'd gotten an
> error or warning.
Ditto. I still find this in my own code, even though I've known better
for years.
-- c
This is assuming that the static people always use the '.. if 0' paradigm.
--
You live and learn (although usually you just live).
I don't quite follow. Are you saying that an ANDOP which finds its LH arg
false, and who's RH arg is in some way flagged as containing a my, should
produce a run-time warning?
So the change from the current practice is that if $quux is *never* false,
then one compile-time warning is reduced to no warnings; if $quux is ever
false, then one compile-time warning is replaced with 1+ run-time
warnings?? Since there's a good chance that $quux will be false at least
once, I don't see how this would buy us anything. Or have I misunderstood?
Another thing I considered but didn't do (becuase I wasn't sure how to do
it), was not to warn on my declarations contained in a block that can
only be executed once, ie in a CvUNIQUE sub (ie a file or eval), with
no loop constructs surrounding the my, and no labels beteween it and the
top of the outermost block. This would silence quite a few of the things
I had to fix in core modules along the lines of
# -- start of file
...
my $flag = 1 if $configp{flag};
But then there's the philosophical point of are we trying to discourage
all use of the construct, or just potentially harmful uses - ie whose
behaviour currently is buggy, or who's behaviour would change if we fixed
the bug (eg those people using as a static var).
--
SCO - a train crash in slow motion
I didn't say lots of modules, I said *lots* of modules. That's why
I think my (d) proposal is not so bad. If it can be reasonably implemented
without slowing everything down. (perhaps with a part during compilation to
spot potentially dangerous areas before emitting the warning at run time.)
(c) Even if there are bug free potential uses of this feature, it seems
like it is still a bug waiting to happen. Every time I've done it, it
was a bug that did happen. Accidentally. I sure wish I'd gotten an
error or warning.
--
Glenn -- http://nevcal.com/
===========================
The best part about procrastination is that you are never bored,
because you have all kinds of things that you should be doing.
Forgive me if this is rehashing old ground, but what exactly is the
recommended replacement for the static variable hack? perldoc's
prophecies of doom and chaos are all very well, and I can understand
that if the current behaviour really is sensitive to recondite
implementation details that something would need to be done, but the
humble end-user might hope for something more constructive.
Is the problem with the "my $x = 0 if 0" construct that:
a) the semantics are ill-defined; or
b) the semantics are ill-defined within closures; or
c) the implementation can't support the well-defined semantics?
The word "just" in the following from perlsub.pod is rather odd:
If you do want to create something like C's static variables, just
enclose the whole function in an extra block, and put the static
variable outside the function but in the block.
Is this really what people are supposed to do to fix their 'if 0'
code?
Anthony
The current implementation is regarded as a bug, which does not do what
most people expect, but which behaviour a few savvy people exploit.
> The word "just" in the following from perlsub.pod is rather odd:
>
> If you do want to create something like C's static variables, just
> enclose the whole function in an extra block, and put the static
> variable outside the function but in the block.
>
> Is this really what people are supposed to do to fix their 'if 0'
> code?
Yes.
sub f {
my $x if 0
....
}
becomes
{
my $x;
sub f {
....
}
}
or use package vars, or use file-scoped lexicals, or whatever is most
appropriate to the situation at hand.
--
In the 70's we wore flares because we didn't know any better.
What possible excuse does the current generation have?
Ah - okay. That clarifies what I was finding difficult. None of
these solutions have the same "feel".
Has it been considered to introduce a dedicated syntax for this?
my $x : static = 0; or something similar.
Perhaps I might outline why I think this would be worthwhile.
One situation, for example, that one often uses such a static
variable is to preserve an optimization hint - a cache
of a previous input, or similar.
My experience at least is that while useful, such structures
can be prone to bugs which are relatively difficult to find:
either it's the existence of state which makes things more
complex, or merely that if the cache breaks it doesn't affect
the results, only the performance.
So just as a design principle, it's nice to keep such
cacheing code tightly localized and grouped.
The 'C' heritage provides a recognizable idiom for this
with use of the "static" variable qualifier. Perl has
until now being doing the same thing with the admittedly
recondite 'if 0' clause.
With the three new solutions:
1) Wrapping the entire sub in an extra block has an excessive
indentation impact compared to the 5 or 6 chars
of the C or current perl syntax;
2) Moving the variable to file scope breaks the code grouping,
and over-emphasises the cache variable, which is really
a logically invisible micro-implementation detail.
3) Using a package var reduces the strength of the privacy,
and indeed suggests that the variable isn't supposed to
be private - else why put it in the symbol table?
I'd acknowledge that these are all style issues, and so not
critical in that the needed functionality is unquestionably
available. But perl design has a long history of considering
syntactic expressiveness as important - huffman-coding,
end-weighting, etc.
One might suggest that the current use of the 'if 0' construct
is in the best tradition of such principles.
(Well, OK, maybe that's stretching things a little...)
Tightening the logical consistency of conditional declarations
is undoubtedly a good goal. But so would be preserving some
way to define static variables with the existing very
satisfactory syntactic weight and balance.
Rgds
Anthony
At least with a non-constant initializer I think this is a bad
match for perl, because it's not clear when the initializer should
be executed.
If you say "compile time", then something like this will
probably surprise people:
my $b = 5;
sub fun {
my $x : static = $b+4;
}
because at compile time $b doesn't have a value yet.
And executing it at runtime (so just after $b=5 was done) would
also be very confusing. People don't expect things in the body of a
function to run at that point in time.
What should this do and why ?
my $b = fun();
sub fun {
my $x : static = $b+4;
return $x+3;
}
With the "standard" way to do static in perl you write
$b = 5;
{
my $x = $b+4;
sub fun {
return $x+3;
}
}
and here it's absolutely clear when $x gets initialized: it uses
the runtime model, and the code also LOOKS like that, so that's
what both a code writer and reader will expect.
And with only constant or no initializer, it doesn't feel very
perlish to me.
Good point.
> What should this do and why ?
>
> my $b = fun();
>
> sub fun {
> my $x : static = $b+4;
> return $x+3;
> }
Hmm...
> With the "standard" way to do static in perl [...]
> [...] it's absolutely clear when $x gets initialized: it uses
> the runtime model, and the code also LOOKS like that, so that's
> what both a code writer and reader will expect.
True, though arguments based on familiarity always rather favour
the status-quo. My point was only that the "standard" way
LOOKS inside-out and does horrible things to the code indentation
for larger functions, rather than that the semantics were imprecise.
To try to answer the challenge, then... C++ obviously hit the
same issue when extending C's static to handle objects.
Their solution: "It will be initialized only the first time the
thread of execution reaches its definition." (Stroustrup sec 7.1.2)
I'd suggest perl could do just the same.
So the above would return '7' along with a warning that b was
undef at the time it was added to 4. (assuming that my mental
perl interpreter isn't broken in other ways...)
> And with only constant or no initializer, it doesn't feel very
> perlish to me.
Agreed.
Anthony
This communication is for informational purposes only. It is not intended as
an offer or solicitation for the purchase or sale of any financial instrument
or as an official confirmation of any transaction. All market prices, data
and other information are not warranted as to completeness or accuracy and
are subject to change without notice. Any comments or statements made herein
do not necessarily reflect those of J.P. Morgan Chase & Co., its
subsidiaries and affiliates.
I'm not sure I agree that it looks inside-out, though I may just be
overly used to it - I've been creating my static variables that way
for a long time. The worst I can say of it is that it introduces one
extra level of indentation for the code, and uses up 3 or 4 extra
lines. Which is in part an argument for keeping to short subroutine
bodies rather than changing the language. :)
:To try to answer the challenge, then... C++ obviously hit the
:same issue when extending C's static to handle objects.
:Their solution: "It will be initialized only the first time the
:thread of execution reaches its definition." (Stroustrup sec 7.1.2)
That would certainly have been my first assumption. I'm not sure if
there is an easy way to implement it that way though.
I believe the perl6 track had some plans to introduce a similar 'make
this variable static' attribute, but I think I remember them wanting
specifically to avoid calling it 'static'.
Closures still become tricky though: I would guess that each closure
gets its own clone of a static variable declared within it, and each
time any such closure is executed for the first time the variable must
be initialised regardless of what has happened in other clones. Which
means you can't signal this just by excising a 'do this once' block
from the optree after executing.
Hugo
Sounds very plausible. I never quite understood the objection to what
seem to me perfectly good precedents, but it does seem to be regarded
as important.
my $x : once = 0; -or- my $x : init = 0;
are perhaps more in keeping with the house style. I don't feel strongly.
> Closures still become tricky though: I would guess that each closure
> gets its own clone of a static variable declared within it, and each
> time any such closure is executed for the first time the variable must
> be initialised regardless of what has happened in other clones. Which
> means you can't signal this just by excising a 'do this once' block
> from the optree after executing.
Yes. It would seem reasonable though to avoid that problem simply by not
defining it that way, instead making all closures share the instance.
Anthony
Anthony> If you do want to create something like C's static variables, just
Anthony> enclose the whole function in an extra block, and put the static
Anthony> variable outside the function but in the block.
Anthony> Is this really what people are supposed to do to fix their 'if 0'
Anthony> code?
Sure. I see nothing wrong with:
BEGIN {
my $x = 42;
my @y = qw(hello world);
sub function_1 {
... uses $x and @y as private vars
}
sub function_2 {
.. .uses $x and @y as private vars
}
}
etc etc.
Not only do you get static vars... you get vars you can share
amongst many subroutines, like a "regional" var instead of a global.
The "BEGIN" ensures that you don't accidentally execute the
initializer twice... it gets run once at compile time, then
disappears.
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<mer...@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
> Has it been considered to introduce a dedicated syntax for this?
>
> my $x : static = 0; or something similar.
It always seemed to me that this is how "our" should have been defined.
I even used:
sub foo {
our $stuff = "just once";
}
once in a program, and was shocked to find that it didn't do what I
thought it would.
--
Aaron Sherman <a...@ajs.com>
Senior Systems Engineer and Toolsmith
"It's the sound of a satellite saying, 'get me down!'" -Shriekback
Aren't they? Please elaborate!
--
The perl5 internals are a complete mess. It's like Jenga - to get the
perl5 tower taller and do something new you select a block somewhere in
the middle, with trepidation pull it out slowly, and then carefully
balance it somewhere new, hoping the whole edifice won't collapse as a
result.
- Nicholas Clark, based on an original by Simon Cozens.
Er, doesnt this bring up the problem that BEGIN blocks arent always
executed? Or have I missed something on that subject?
yves
My understanding is that there are circumstances where BEGIN blocks do not
execute. Probably im confused, but I could have sworn that this is true.
(Although now that I think about it more maybe I meant INIT blocks...)
Hence the reason i asked, and didnt state.
:-)
Yves
Yep. Thats it. Sorry about that.
Although given this point when the docs on statics are changed it may be
worth making clear that these block types are not appropriate for this type
of usage...
Yves
Ronald> I think this may be the case for mod_perl; a CGI script could be run
Ronald> multiple times, but the BEGIN block is only executed once per child
Ronald> process. Someone who knows more about mod_perl could say for sure. :)
But it will run exactly once at the right time... to initialize the statics
to what they should be.
>The current implementation is regarded as a bug, which does not do what
>most people expect, but which behaviour a few savvy people exploit.
>
Could someone please post a link to a discussion of what exactly the
current implementation does
with this construct?
> >> Er, doesnt this bring up the problem that BEGIN blocks arent always
> >> executed? Or have I missed something on that subject?
> > Aren't they? Please elaborate!
>
> My understanding is that there are circumstances where BEGIN blocks do not
> execute. Probably im confused, but I could have sworn that this is true.
> (Although now that I think about it more maybe I meant INIT blocks...)
You probably think about CHECK and INIT blocks, which are executed
I think this may be the case for mod_perl; a CGI script could be run
multiple times, but the BEGIN block is only executed once per child
process. Someone who knows more about mod_perl could say for sure. :)
Ronald