UPDATE - Okay, Devel::GetSymbols it will be. I also added subs(). Updated code below.

Hi fellow monks,

Once in a while, one of us asks how all subs can be exported. Some want a list of subs in a certain package for debugging (I'd use it on a badly documented OO XS module).
We can already do that! We don't need a module for that!

However, the code that's used for that, depends on a lot of magic, and I don't think it really looks clean. I'd rather type it once, and then just use a nice interface to it.
Having this in a module would also save time when someone asks how all subs can easily be exported. We could just answer
use Symbol::List; @EXPORT_OK = Symbol::List::symbols('CODE');
and go on with our own hacking :)

I present you the module here, before I upload it to CPAN. If you feel it needs a change, or think CPAN should not be poluted with such crap, please do respond. If you like the idea and would love to have it on CPAN, please tell why. It's also possible this module already exists under a different name - please let me know.

(The code is after the readmore tag)
Package Devel::GetSymbols; use strict; use vars qw($VERSION @EXPORT_OK); use base 'Exporter'; use Carp; @EXPORT_OK = qw(symbols subs); $VERSION = '0.01'; no strict 'refs'; sub symbols { my ($type, $package) = @_; $package = (caller)[0] unless defined $package; croak 'Usage: symbols(type[, package])' unless defined $type; grep defined *{"${package}::$_"}{$type}, keys %{"${package}::"} } sub subs () { symbols( CODE => (caller)[0] ) } 1; __END__ =head1 NAME Devel::GetSymbols - get a list of symbols that match a certain type =head1 SYNOPSIS use Devel::GetSymbols qw(symbols subs); my @subroutines = symbols('CODE'); my @subroutines = subs(); # equal # @subroutines includes 'symbols', because it was imported # into this package. use Data::Dumper; print "$_\n" for symbols('SCALAR', 'Data::Dumper'); use base 'Exporter'; @EXPORT_OK = symbols('CODE'); # Yuch. @EXPORT_OK = subs(); # Ditto. @EXPORT = grep /^[A-Z_]+$/, symbols('CODE'); # Export constants =head1 DESCRIPTION This module just does a grep on some keys, but can save a lot of devel +opment time. =over 10 =item symbols Takes type and optional package name as arguments and returns a list o +f symbols that are of that type and in that package. Defaults to the calling pac +kage. Type can be one of qw(ARRAY CODE FORMAT GLOB HASH IO SCALAR). I guess +C<CODE> will be used most :) =item subs Shorthand for C<symbols('CODE')>. Does not take arguments (use C<symbo +ls> if you want to get it from another package). =back =head1 KNOWN BUGS None yet =head1 AUTHOR Juerd <juerd@juerd.nl> =cut

Replies are listed 'Best First'.
Re: Symbol::List
by metadoktor (Hermit) on Jan 23, 2002 at 16:34 UTC
    If I understand what you're saying....you're replacing the following:
    use Exporter(); @ISA=qw(Exporter); @EXPORT_OK=qw(sub1 sub2 sub3 ... subn);
    with:
    use Symbol::List; @EXPORT_OK = Symbol::List::symbols('CODE');
    That isn't saving much effort but it's a nice idea nonetheless. :)

    I think it would unnecessarily export private subs too! That is something you might not want to do.

    metadoktor

    "The doktor is in."

      Well, think of a module which contains just constants used in other modules/programs.
      And imagine you have LOTS of them!

      You'll love a way to export them with something simple like @EXPORT_OK = Symbol::List::symbols('CODE');.

      I think the module is a great idea.

      Please note: It's not just for exporting subs. Symbol::List::symbols returns a list of symbols, which can be useful in many ways. If it were just for exporting, I'd probably have created Exporter::ExportAll :)

      Only lexicals are private, and those aren't in the symbol table. Naming a sub so it starts with an underscore means it's "private" in many cases, but doesn't have to. grep is great for selecting things, and it's not hard at all:
      grep !/^_/, symbols('CODE'); # non-"privates" grep !/[^A-Z0-9_]/, symbols('CODE'); # "constants"

      2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

Re: Symbol::List
by busunsl (Vicar) on Jan 23, 2002 at 16:54 UTC
    I like it!

    What I'd like to see in it too, was to have the possibility to further restrict contents of the result by a regular expression.

    I know, you could do something like:

    @EXPORT_OK = grep /^[^_]/, Symbol::List::symbols('CODE');
    to filter out subs beginning with '_', but as you do a grep in symbols() already, it would be more convenient to pass a regex.
      I don't think passing a regex adds much, because grep is so easy to use. And after all, it's what grep is for.
      @EXPORT_OK = grep !/^_/, Symbol::List::symbols('CODE');


      BTW, Symbol::List is not just for exporting :)

      2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

(tye)Re: Symbol::List
by tye (Sage) on Jan 24, 2002 at 04:22 UTC

    Since this is meant to help people who are developing modules, it should be under the Devel:: namespace. I originally /msg'd this request to Juerd who requested I post it.

    Currently, there are tons of modules that are not well named (including some very popular and/or important ones). Symbol.pm and Symbol::Approx::Sub are two of them. There really should be much fewer names at the top of the namespace and "Symbol" is not a good top-level name. I much prefer Devel::ListSymbols for this module (and Net::CGI for CGI.pm, Debug for DB, BackEnd for both B and O, ...).

            - tye (but my friends call me "Tye")

      Since this is meant to help people who are developing modules

      I never actually stated what it was meant for, except for having a function that returns a list of symbols of a certain type in a certain package. It's useable for exporting, but I actually thought of that one after creating the module (I'd not have bothered with a generic function if I only cared about exporting, I would just have made some extention to Exporter).

      "Symbol" is not a good top-level name

      I think it's a very good name. I think it's logical to group modules by what they do, instead of by who will use it in what kind of script/module.
      LWP::Simple is good, Net::HTTP::LWP::Simple would be bad. XML::Parser is good, Data::XML::Parser would be less good. Etcetera. I think the Symbol top level namespace was a good choice, and I'm glad it exists.
      Symbol::List would need no description, and many people would use it. Devel::SymbolList would indicate it has something to do with development only (we're not calling Exporter Devel::Exporter just because its sole purpose is to ease module development) which scares off some users. This module is not for power users. Power users have always written their own symbol grabbing code, and will probably continue to do so.

      I much prefer Devel::ListSymbols for this module

      The module was made to generate a list of symbols, not to list symbols. But that's a very minor issue.

      2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

      I completely agree with tye: it should be in the Devel:: namespace. And Juerdje++ for the module!

      Jouke Visser, Perl 'Adept'
      Using Perl to help the disabled: pVoice and pStory
      Two saints say the Devel:: namespace is the place for this module to be, so I guess I'll have to change that then :)
      How do you feel about the name Devel::Symbols? It's clear, short - and the plural indicates what it does. I'd like to avoid "list", if I'm going to put this outside of Symbol::, and I don't think Devel::Symbol::List would be such a great idea.

      Let me know - reply and tell me what you think.

      2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

        Hmm. Well. Im a bit dense sometimes but I dont think I would immediately know what the package was for from Devel::Symbols, maybe Devel::PackgeSymbols?

        Just a thought.

        Yves / DeMerphq
        --
        When to use Prototypes?

        I don't see anything wrong with Devel::Symbol::List - it's not like it does anything more than this name suggests. To me Devel::Symbols sounds like a big module. If you don't want the extra level of ::, how about Devel::SymbolList?
           larryk                                          
        perl -le "s,,reverse killer,e,y,rifle,lycra,,print"
        
Re: Symbol::List
by Juerd (Abbot) on Jan 25, 2002 at 00:32 UTC
    Some discussion has been going on about the name of the module. Currently, I like tye's suggestion (Devel::GetSymbols).

    Any real objections? If so, let me know NOW :) (and provide a good alternative).

    2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$