On Fri, Apr 20, 2012 at 04:55:12PM +0100, Dave Mitchell wrote:
> On Fri, Apr 20, 2012 at 12:37:55PM +0100, Nicholas Clark wrote:
> > constant.pm now takes advantage of the "proxy constant subroutines"
> > on all versions from 5.10.0 onwards. It no longer users the fragile
> > "feature" under discussion here, that
> >
> > *foo::bar = sub () { $baz; }
>
> Well, having a quick look at constant.pm, it may use the new method as its
> primary route, buts there's still plenly of places where it uses the old
> mechanism, even down to
>
> my $const = $] > 5.009002;
> *_CAN_PCS = sub () {$const};
Hmmm, bother. Although that can probably be solved like this:
*_CAN_PCS = $] > 5.009002 ? sub () { 1 } : sub () { 0 };
(not tested)
> [ just by-the-by, I don't understand why constant.pm is written in such a
> way as to be able to run under old perls; its not as if its a dual-life
> CPAN distribution ]
It is a dual-life CPAN distribution. See https://metacpan.org/module/constant
> I don't know enough about how the new method works to be abloe to say
> whether it can be rewritten to avoid sub(){$x} completely, or whether
> we need to add some sort of XS mechanism for the general case.
I thought that it didn't use them, but there is one obvious bit that is still
live, a fallback in the else block here:
# The constant serves to optimise this entire block out on
# 5.8 and earlier.
if (_CAN_PCS && $symtab && !exists $symtab->{$name}) {
# No typeglob yet, so we can use a reference as space-
# efficient proxy for a constant subroutine
# The check in Perl_ck_rvconst knows that inlinable
# constants from cv_const_sv are read only. So we have to:
Internals::SvREADONLY($scalar, 1);
$symtab->{$name} = \$scalar;
++$flush_mro;
} else {
*$full_name = sub () { $scalar };
}
I think that's only hard to work round in the case of naming a constant
with the same name as something else that already exists. I suspect that
that's rare, and could be replaced with a string eval, or cheating somewhat
with an intermediate assignment to known-free symbol table entry
(eg a name within %constant::) and then "exporting" it to the right place.
I'm not so sure about this:
} elsif (@_) {
my @list = @_;
*$full_name = sub () { @list };
but did list inlining *ever* actually inline? I'm going to guess "no", given
that these lines
In the current version of Perl, list constants are not inlined
and some symbols may be redefined without generating a warning.
date from 5.004 when constant.pm was added
http://perl5.git.perl.org/perl.git/blame/HEAD:/dist/constant/lib/constant.pm#l347
> So, I think we should remove this 'feature'.
Given that constant doesn't *need* it any more, there seems to be consensus
that it can go.
> If anyone is using it as intended, then the worst they'll get is
> a performance decrease, with a const sub downgraded to a real sub that
> returns the expected value. Perhaps we could issue a warning, with
> perldiag.pod explaining what to do if you really wanted a const sub, and
> to stick a 'return' in to defeat the warning if you didn't want it.
I was initially thinking "do we really need a warning? No"
but then I suspect that for initial development purposes we ought to be
able to have it as a compile-time fatal error, to make sure we spot
everywhere in core that still has it. (Such as that fallback code in
constant.pm)
Nicholas Clark