Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Removing CODE slot in typeglob / Reversing "use subs ...;"

by lodin (Hermit)
on Jan 03, 2008 at 17:38 UTC ( #660264=perlquestion: print w/ replies, xml ) Need Help??
lodin has asked for the wisdom of the Perl Monks concerning the following question:

I'm attempting to write a constant::lexical pragma and the only unresolved issue as of now is that the constant names are valid barewords even though the constant subroutine has been undefined.

use 5.010; use strict; sub FOO () { 'foo' } BEGIN { undef &FOO } say defined &FOO ? 'subroutine defined' : 'subroutine undef'; say eval 'my $false; FOO if $false; 1' ? 'FOO allowed' : 'FOO not allowed' ; __END__ subroutine undef FOO allowed
This is a major issue as one of the great features of constants is that they normally give compile-time errors if not defined.

I don't see any way to do this in pure Perl. I've browsed perldata, perlapi, perlguts, and perlintern for any ideas but I haven't found anything useful. I don't grok most of the guts. Is it possible using XS? Of course, XS is the very last resort.

lodin

Update: Added stricture and my $false; in the eval to make the test actually work.

Comment on Removing CODE slot in typeglob / Reversing "use subs ...;"
Select or Download Code
Replies are listed 'Best First'.
Re: Removing CODE slot in typeglob / Reversing "use subs ...;"
by shmem (Canon) on Jan 03, 2008 at 20:08 UTC
    The only way I see is saving the typeglob, destroying it and re-creating it with all but the CODE slot:
    use 5.010; use strict; our $FOO; BEGIN { $FOO = 'still foo'; } sub FOO () { 'foo' } BEGIN { *BAR = *FOO; say "in BEGIN (1): \$FOO = '$FOO'"; undef *FOO; say "in BEGIN (2): \$FOO = '$FOO'"; *FOO = *BAR{SCALAR}; undef *BAR; } say defined &FOO ? 'subroutine defined' : 'subroutine undef'; say eval 'my $false; FOO if $false; 1' ? 'FOO allowed' : 'FOO not allowed' ; say $FOO; __END__ in BEGIN (1): $FOO = 'still foo' in BEGIN (2): $FOO = '' subroutine undef FOO not allowed still foo

    update: tweaked the code to more closely resemble the OP's.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      The only way I see is saving the typeglob, destroying it and re-creating it with all but the CODE slot

      Yup, that is correct. That is how we do it in Class::MOP::Package, and when I was writing that bit at the YAPC::NA 2005 hackathon I queried the collective wisdom of the gurus in attendence (larry, audrey and chromatic to name a few) and they all agreed that was the only way. And AFAIK there is no cleaner way to do it in XS either.

      -stvn
        I wonder, is that a design accident or intended? you can assign to a typeglob slot (assigning a specific ref to that typeglob), but you cannot undef its value, you have to destroy the whole glob. You cannot assign e.g. an 'undefined subref' to a CODE slot, because... no such thing. Something undef is not a CODE ref.

        Did you get told the rationale behind that? Does anybody know? Cloning a typeglob to get rid of one entry in it looks like "useless use of hoops" to me. IMHO there should be a syntax to remove slots, keys, values and all, as delete does with plain hashes.

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      The reason I didn't like this was that you couldn't access formats using *foo{THING} in Perl 5.6. I'd missed that *foo{FORMAT} now works (perl58delta). *foo{FORMAT} is not mentioned in either perldata or perlmod, but I found it in perlref. Really, that's not the first place I'd look to see which slots there are in a typeglob ...

      Thanks for forcing me to try (and fail) to proof that *foo{FORMAT} doesn't work, because that's what I originally intended to reply with. :-)

      *foo{FORMAT} and the resulting *foo{NAME} for the no-longer-constants was my only conserns, both of which are now solved. So I guess that marks the issue solved, unless you can see some other pitfall with this technique.

      lodin

Re: Removing CODE slot in typeglob / Reversing "use subs ...;"
by BrowserUk (Pope) on Jan 03, 2008 at 18:03 UTC

    I've done no real testing (my food is ready), but is this the effect you are looking for?

    #! perl -slw use strict; use 5.010; sub FOO () { 'foo' } BEGIN { undef $::{FOO} } say defined &FOO ? 'subroutine defined' : 'subroutine undef'; say eval 'FOO if $false; 1' ? 'FOO allowed' : 'FOO not allowed'; __END__ C:\test>660264.p10 subroutine undef FOO not allowed

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Beware of the $false in there. Your eval fails because you turned on stricture, but even with my $false; it fails, so that's good. Unfortunately it works too well.

      undef $::{FOO} is the same as undef *FOO and that undefined the whole typeglob.

      our $FOO = 'foo'; undef $::{FOO}; print defined $FOO ? 'defined' : 'undef'; __END__ undef
      I only want to remove the CODE slot in the typeglob.

      lodin

        Again, I'm only adressing the symptoms rather than thinking things through, but how's this?

        #! perl -slw use strict; use 5.010; our $FOO = 'fred'; sub FOO () { 'foo' } BEGIN { undef $::{FOO}{CODE} } say defined &FOO ? 'subroutine defined' : 'subroutine undef'; say eval 'FOO if $false; 1' ? 'FOO allowed' : 'FOO not allowed'; print $FOO; __END__ C:\test>660264.p10 subroutine defined FOO not allowed fred

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://660264]
Approved by McDarren
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (7)
As of 2015-07-08 07:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (96 votes), past polls