Front page | perl.perl5.porters |
Postings from July 2009
Re: Hooks at the end of a scope during compile time
Thread Previous
|
Thread Next
From:
Ben Morrow
Date:
July 17, 2009 13:04
Subject:
Re: Hooks at the end of a scope during compile time
Message ID:
20090717200419.GA46497@osiris.mauzo.dyndns.org
Quoth perl@profvince.com:
>
> I prefer the variable approach because not only it provides some means
> of introspection, but also because it's easier to conditionnaly store a
> destructor that way than with a block. Finally, adding a new variable is
> just much simpler to implement.
I was hoping to postpone this discussion until after 5.10.1 is out (and
until after I'd finished the implementation ;)) but never mind... :)
I don't yet understand what the need is for introspection and/or an
object that can have state. I can see that Florian's tests test that the
object maintains its state correctly, but I don't really see what you
could usefully do with it.
It would be relatively easy to add an API to check what blocks are
attached to the currently running scope, or will be attached to the
currently compiling scope. Admittedly it would be somewhat harder to
tell them apart if they are just CVs rather than objects, but AFAICS it
should be possible to bless the CVs, which makes a full object available
to those who want it. If all you want is (say) a count of how many times
'use Foo' has been called in this scope, then all these blocks will be
closures so you just arrange to close over an appropriate variable.
In terms of conditionally adding a block, I don't see how
use Block::Util "install_block";
sub import {
if (...) {
install_block SCOPECHECK => sub {...};
}
}
is any harder than pushing onto an array. The literal block syntax is
for creating a block attached to the lexically-surrounding scope,
something that @{^C_S_C} doesn't support at all, except through the
rather ugly
{
BEGIN {
push @{^COMPILE_SCOPE_CONTAINTER},
Scope::Guard->new(sub {...});
}
}
In fact, given that the current implementation simply has a AV of blocks
to be installed (and possibly run) at the end of compiling the current
scope, I don't see why that AV couldn't be exposed as @{^PAD_BLOCKS} or
some such (I'm not attached to that name, it's just what I call them
internally). It would have to have magic to make sure all its entries
were CVs and CvSPECIAL and appropriately named (and to translate from a
C-level AV-of-CVs to a Perl-level array-of-subrefs), but that's easy.
In the end, I find the idea of having to create an object with a DESTROY
method when all you want to do is run some code at the appropriate time
rather messy. We already have UNITCHECK: it seems to me that SCOPECHECK
is just an extension of the same idea.
Obviously you are correct that Florian's idea is simpler to implement:
apart from anything else, Florian has a patch ready to be applied and
I'm still working on mine :). One strong thing in favour of just having
a variable would be if the general pad-block mechanism were considered
too much to go into maint (it needs both a new OP and a new type of pad
entry: would either of those automatically disqualify it?).
A potential compromise might be to add @{^PAD_BLOCKS} (or whatever;
perhaps @{^SCOPE_BLOCKS} would be a better Perl-level name) now, which
holds a list of subrefs to be called (*not* objects to be destroyed) at
the end of compiling the current scope. Then the other blocks can be
added later, with the code assuming that anything in there that isn't
CvSPECIAL should be treated as a SCOPECHECK.
> The new control blocks from Perl 6 would definitely make a great
> addition to Perl 5, but they're a different issue that the dynamic scope
> end one.
Well, clearly I don't think so :), but if people disagree I'd be happy
to go through and strip out SCOPECHECK before submitting a patch.
One further issue here that nothing currently addresses is that things
that are supposed to have lexical scope shouldn't leak out into do FILE/
require/use and should leak out into eval STRING. autodie has some
rather hairy code to try to work around this, and I'm not at all sure it
doesn't have side-effects. It seems to me that this could be avoided
entirely with REQUIRE and ENTEREVAL blocks that got invoked at the
appropriate times.
Ben
Thread Previous
|
Thread Next