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

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

Thread Previous | Thread Next
From:
Nicholas Clark
Date:
April 20, 2012 09:23
Subject:
Re: [perl #24250] "return" required in some anonymous closures
Message ID:
20120420162347.GZ9069@plum.flirble.org
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

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About