in reply to Re: accessing stashes
in thread accessing stashes

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?

Replies are listed 'Best First'.
Re^3: accessing stashes
by ikegami (Patriarch) on Mar 01, 2019 at 19:14 UTC

    $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]


    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 );.

      Something changed in 5.22. $My::{$symbol} can return a code reference or -1 instead of a glob.

      The following is therefore needed:

      sub get_code_ref_by_fqn { # Fully qualified name my ($fqn) = @_; my @pkg_name_parts = split /::/, $fqn; my $symbol = pop(@pkg_name_parts); my $pkg = \%::; for (@pkg_name_parts) { $pkg = $pkg->{$_.'::'} or return undef; } my $glob_or_code = $pkg->{$symbol} or return undef; return $glob_or_code if ref($glob_or_code); return undef if ref(\$glob_or_code) ne 'GLOB'; return *$glob_or_code{CODE}; }

      But you know what, let's just leave those dirty details to Perl.

      sub get_code_ref_by_fqn { # Fully qualified name my ($fqn) = @_; no strict qw( refs ); return undef if !defined(&$fqn); return \&$fqn; }

      Above tested using

      use 5.012; use warnings; sub Foo::Bar::y; sub Foo::Bar::z { } say get_code_ref_by_fqn('Foo::Bar::x') // '[undef]'; say get_code_ref_by_fqn('Foo::Bar::y') // '[undef]'; say get_code_ref_by_fqn('Foo::Bar::z') // '[undef]';
      This is *exactly* what I was looking for - would you be so kind to rewrite my script above with your syntax (am interested in package "main") as I seem to be too drunk to do it myself and my attempts don't compile...

        Main is %:: (or %main:: (or %main::main:: (...))) instead of %My::.