develooper Front page | perl.perl5.porters | Postings from April 2012

Re: [perl #24250] "return" required in some anonymous closures

Nicholas Clark
April 20, 2012 09:23
Re: [perl #24250] "return" required in some anonymous closures
Message ID:
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:
> > 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, 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 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

> 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;
		} 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 was added

> 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

Nicholas Clark Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About