Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

accessing stashes

by morgon (Priest)
on Mar 01, 2019 at 16:57 UTC ( #1230721=perlquestion: print w/replies, xml ) Need Help??

morgon has asked for the wisdom of the Perl Monks concerning the following question:

Hi

I knew this once, but I cannot remember the details and I am too stupid to find it online, so I hope for some feedback here...

I know that the symbol-table for package main is %{main::}.

The symbol-table has an entry for each symbol that points to a stash which has slots for the different variable types (SCALAR, CODE etc)

What is the syntax to find out whether a symbol has a code-reference in that symbol's stash?

Many thanks!

Replies are listed 'Best First'.
Re: accessing stashes
by choroba (Archbishop) on Mar 01, 2019 at 17:11 UTC
    You can do that with the symbol table, but using defined and exists is cleaner.
    #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; { package My; sub one { print "123"; } sub two; } say ${My::}{one}; # *My::one say ${My::}{two}; # -1 say ${My::}{three}; # say defined *My::one{CODE}; # 1 say defined *My::two{CODE}; # 1 say defined *My::three{CODE}; # say exists &My::one; # 1 say exists &My::two; # 1 say exists &My::three; # say defined &My::one; # 1 say defined &My::two; # say defined &My::three; #

    Update: added the first paragraph of says.

    Update 2: Interestingly, a forward declared sub with prototypes returns the prototypes with the first syntax:

    sub four (&@); # ... say ${My::}{four}; # &@

    Update 3: ... unless you add an attribute, too, which makes it output the glob name.

    sub five (&@) :method; say ${My::}{five}; # *My::five

    Update 4: The -1 is printed only if you remove all other mentions of My::three, otherwise *My::three is printed.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      That comes close, but I want something like this (the code below does NOT work):
      use strict; sub hubba { } for my $symbol qw(hubba bubba) { print "$_: "; print defined *My::$symbol{CODE} ? "yep": "nope"; print "\n"; }
      That should print
      hubba: yep bubba: nope
      How can I do that?

        $My::{$symbol} returns a glob.

        *NAME{SLOT} accesses a glob's slot.
        *BLOCK{SLOT} accesses a glob's slot.
        *$NAME{SLOT} accesses a glob's slot.
        EXPR->*{SLOT} accesses a glob's slot.[1]

        So,

        my $glob = $My::{$symbol}; $glob && *{ $glob }{CODE} $glob && *$glob{CODE} $glob && $glob->*{CODE}

        1. Requires Perl 5.24+. Available in Perl 5.20+ by adding both use feature qw( postderef ); and no warnings qw( experimental::postderef );, or by adding use experimental qw( postderef );.
Re: accessing stashes
by NetWallah (Canon) on Mar 01, 2019 at 17:28 UTC
    >perl -E " sub testing{234}; ref($main::{$_}) eq qq|CODE| and say q +q|-->\$main::$_ is a Code ref| for sort keys %main::" -->$main::testing is a Code ref

                    As a computer, I find your faith in technology amusing.

      It works for me in blead, but doesn't output anything in 5.18.2. Also, it doesn't seem to work for other packages than main.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      It also doesn't work if there's a scalar/array/hash/... with the same name as the sub.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1230721]
Approved by stevieb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (1)
As of 2021-09-18 01:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?